Remove TODO file
[remote/remote-mci.git] / diku_mch / MoteHost.cc
blob7151a377d2bbb2c031d2f910892337b9336d7092
1 #include "MoteHost.h"
3 namespace remote { namespace diku_mch {
5 using namespace remote::util;
7 int MoteHost::clientsock;
8 int MoteHost::plugpipe;
9 Message MoteHost::msg;
10 DeviceManager MoteHost::devices;
11 Configuration MoteHost::config;
13 void MoteHost::lookForServer()
15 while (1) {
16 std::string host = config.vm["serverAddress"].as<std::string>();
17 uint16_t port = config.vm["serverPort"].as<uint16_t>();
18 uint64_t secs = config.vm["serverConnectionRetryInterval"].as<uint64_t>();
20 Log::info("Connecting to %s on port %u...", host.c_str(), port);
21 clientsock = openClientSocket(host, port);
22 if (clientsock >= 0) {
23 Log::info("Connected!");
24 setKeepAlive(clientsock, 3, 120, 30);
26 try {
27 serviceLoop();
28 close(clientsock);
30 } catch (remote::protocols::MMSException e) {
31 Log::error("Exception: %s", e.what());
33 } catch (remote::error e) {
34 Log::error("Exception: %s", e.what());
36 Log::error("Disconnected");
38 } else {
39 Log::error("Connection failed");
42 Log::info("Reconnecting in %llu seconds...", secs);
43 usleep(secs * 1000000);
47 void MoteHost::serviceLoop()
49 std::string eventPipe = config.vm["usbPlugEventPipe"].as<std::string>();
50 fd_set fdset;
52 remove(eventPipe.c_str());
53 if (mkfifo(eventPipe.c_str(), 0666) == -1)
54 throw remote::error(errno, "Failed to make fifo " + eventPipe);
56 plugpipe = open(eventPipe.c_str(), O_RDONLY | O_NONBLOCK);
57 if (plugpipe < 0)
58 throw remote::error(errno, "Failed to open fifo " + eventPipe);
60 // the first thing to do is send all current mote information to the server
61 devices.refresh(config.vm["devicePath"].as<std::string>());
62 Log::debug("Sending mote list to server");
63 MsgPlugEvent msgPlugEvent(PLUG_MOTES);
64 if (makeMoteInfoList(devices.motes, msgPlugEvent.getInfoList())) {
65 HostMsg hostMsg(msgPlugEvent);
66 Message msg;
67 msg.sendMsg(clientsock,hostMsg);
70 Log::debug("Entering service loop");
71 while (true) {
72 int maxfd = rebuildFdSet(fdset);
74 // wait for non-blocking reads on the fds
75 if (select(maxfd+1, &fdset, NULL, NULL, NULL) == -1)
76 break;
78 if (FD_ISSET(clientsock, &fdset))
79 handleMessage();
81 if (FD_ISSET(plugpipe, &fdset))
82 handlePlugEvent();
84 motemap_t::const_iterator moteI = devices.motes.begin();
86 while (moteI != devices.motes.end()) {
87 int p = moteI->second->getFd();
88 if (p > 0 && FD_ISSET(p, &fdset))
89 handleMoteData(moteI->second);
90 moteI++;
93 close(plugpipe);
96 int MoteHost::rebuildFdSet(fd_set& fdset)
98 int p,maxp;
99 Mote* pmote;
100 FD_ZERO(&fdset);
101 motemap_t::const_iterator moteI = devices.motes.begin();
103 // put in valid mote file descriptors
104 maxp = 0;
105 while (moteI != devices.motes.end())
107 pmote = moteI->second;
108 p = pmote->getFd();
109 if (p > 0)
111 if (p > maxp) {maxp = p;}
112 FD_SET(p, &fdset);
114 moteI++;
117 // fd for the connected server
118 FD_SET(clientsock, &fdset);
119 if (clientsock > maxp) {maxp = clientsock;}
120 FD_SET(plugpipe, &fdset);
121 if (plugpipe > maxp) {maxp = plugpipe;}
122 return maxp;
125 void MoteHost::handlePlugEvent()
127 Message msg;
128 // for now, just assume that a plug event occured
129 char c;
130 // empty the pipe
131 int i = 1;
132 Log::info("Handling plug event");
133 while ( i == 1 )
135 i = read(plugpipe,&c,1);
136 if ( i <= 0 )
138 close(plugpipe);
139 plugpipe = open(config.vm["usbPlugEventPipe"].as<std::string>().c_str(),O_RDONLY | O_NONBLOCK);
143 devices.refresh(config.vm["devicePath"].as<std::string>());
145 MsgPlugEvent msgUnplugEvent(UNPLUG_MOTES);
146 if (makeMoteInfoList(devices.lostMotes, msgUnplugEvent.getInfoList()))
148 HostMsg hostMsg(msgUnplugEvent);
149 msg.sendMsg(clientsock,hostMsg);
152 MsgPlugEvent msgPlugEvent(PLUG_MOTES);
153 if (makeMoteInfoList(devices.newMotes,msgPlugEvent.getInfoList()))
155 HostMsg hostMsg(msgPlugEvent);
156 msg.sendMsg(clientsock,hostMsg);
160 bool MoteHost::makeMoteInfoList(motemap_t& motelist, MsgMoteConnectionInfoList& infolist)
162 motemap_t::const_iterator moteI;
164 infolist.clear();
166 for (moteI = motelist.begin(); moteI != motelist.end(); moteI++) {
167 Mote *mote = moteI->second;
168 MsgMoteConnectionInfo info(mote->getMac(), mote->getDevicePath(),
169 mote->getPlatform());
171 infolist.addMoteInfo(info);
174 return motelist.size() > 0 ? true : false;
178 void MoteHost::handleMessage()
180 motemap_t::const_iterator moteI;
181 Mote *mote;
183 if (msg.nonBlockingRecv(clientsock))
185 uint8_t* buffer = msg.getData();
186 uint32_t buflen = msg.getLength();
187 HostMsg hostMsg(buffer,buflen);
189 if (hostMsg.getType() != HOSTMSGTYPE_HOSTREQUEST)
190 throw remote::error("Can only handle hostmote messages!");
192 MsgHostRequest& msgHostRequest = hostMsg.getHostRequest();
193 MsgMoteAddresses& addresses = msgHostRequest.getMoteAddresses();
194 buffer = (uint8_t*)msgHostRequest.getMessage().getData();
195 buflen = msgHostRequest.getMessage().getDataLength();
196 MoteMsg moteMsg(buffer,buflen);
198 moteI = devices.motes.find(addresses.getMac());
200 if (moteI == devices.motes.end())
202 Log::warn("Mote %s unknown!", addresses.getMac().c_str());
203 MsgHostConfirm msgHostConfirm(MSGHOSTCONFIRM_UNKNOWN_MOTE,addresses,msgHostRequest.getMessage());
204 HostMsg msgReply(msgHostConfirm);
205 msg.sendMsg(clientsock,msgReply);
206 return;
209 mote = moteI->second;
211 switch (moteMsg.getType()) {
212 case MOTEMSGTYPE_REQUEST:
213 handleRequest(mote,addresses,moteMsg.getRequest());
214 break;
215 case MOTEMSGTYPE_DATA:
217 MsgPayload payload = moteMsg.getData();
218 mote->writeBuf((const char*)payload.getData(),payload.getDataLength());
219 break;
221 default:
222 throw remote::error("Invalid message type!");
227 void MoteHost::handleRequest(Mote* mote, MsgMoteAddresses& addresses, MsgRequest& request)
229 uint8_t command = request.getCommand();
230 result_t result;
232 Log::debug("Mote %s got command=%u", addresses.getMac().c_str(), command);
234 switch (command)
236 case MOTECOMMAND_PROGRAM:
237 result = mote->program(addresses.getTosAddress(),
238 request.getFlashImage().getData(),
239 request.getFlashImage().getDataLength());
240 // don't confirm until programming is done
241 if (result == SUCCESS)
242 return;
243 break;
244 case MOTECOMMAND_CANCELPROGRAMMING:
245 Log::info("User cancelling programming");
246 result = mote->cancelProgramming();
247 break;
248 case MOTECOMMAND_STATUS:
249 result = SUCCESS;
250 break;
251 case MOTECOMMAND_RESET:
252 result = mote->reset();
253 break;
254 case MOTECOMMAND_START:
255 result = mote->start();
256 break;
257 case MOTECOMMAND_STOP:
258 result = mote->stop();
259 break;
260 default:
261 Log::error("Unkown command %u", command);
262 return;
266 MsgConfirm msgConfirm(command, result, mote->getStatus());
267 MoteMsg moteMsg(msgConfirm);
268 MsgPayload msgPayload(moteMsg);
269 MsgHostConfirm msgHostConfirm(MSGHOSTCONFIRM_OK,addresses,msgPayload);
270 HostMsg hostMsg(msgHostConfirm);
271 Message msg;
272 msg.sendMsg(clientsock,hostMsg);
276 void MoteHost::handleMoteData(Mote* mote)
278 char buf[1000];
279 ssize_t readlen = sizeof(buf);
281 MsgMoteAddresses msgMoteAddresses(mote->getMac());
283 while (readlen == sizeof(buf)) {
284 readlen = mote->readBuf(buf, sizeof(buf));
285 if (readlen > 0) {
286 Log::debug("'%.*s'", readlen, buf);
287 uint32_t len = readlen;
288 MsgPayload msgData;
289 msgData.setPayload(len,(uint8_t*)buf);
290 MoteMsg moteMsg(msgData);
291 MsgPayload msgPayload(moteMsg);
292 MsgHostConfirm msgHostConfirm(MSGHOSTCONFIRM_OK,msgMoteAddresses,msgPayload);
293 HostMsg hostMsg(msgHostConfirm);
294 Message msg;
295 msg.sendMsg(clientsock,hostMsg);
299 // check if we're done programming
300 if (readlen <= 0) {
301 if (mote->getStatus() == MOTE_PROGRAMMING) {
302 Log::info("Programming done!");
303 remove(mote->getImagePath().c_str());
304 result_t result = mote->getChildResult();
305 MsgConfirm msgConfirm(MOTECOMMAND_PROGRAM, result, mote->getStatus());
306 MoteMsg moteMsg(msgConfirm);
307 MsgPayload msgPayload(moteMsg);
308 MsgHostConfirm msgHostConfirm(MSGHOSTCONFIRM_OK,msgMoteAddresses,msgPayload);
309 HostMsg hostMsg(msgHostConfirm);
310 Message msg;
311 msg.sendMsg(clientsock,hostMsg);
317 int MoteHost::main(int argc,char** argv)
319 config.read(argc,argv);
320 Log::open("diku_mch", LOG_INFO);
321 if (config.vm["daemonize"].as<int>()) {
322 switch (fork()) {
323 case -1:
324 Log::error("Failed to fork daemon");
325 exit(EXIT_FAILURE);
327 default:
328 _exit(EXIT_SUCCESS);
330 case 0:
331 Log::info("Running as daemon");
334 setsid();
335 fclose(stdin);
336 fclose(stdout);
337 fclose(stderr);
340 MoteHost::lookForServer();
341 return 0;
346 int main(int argc,char** argv)
348 return remote::diku_mch::MoteHost::main(argc,argv);