3 namespace remote
{ namespace diku_mch
{
5 using namespace remote::util
;
7 int MoteHost::clientsock
;
8 int MoteHost::plugpipe
;
10 DeviceManager
MoteHost::devices
;
11 Configuration
MoteHost::config
;
13 void MoteHost::lookForServer()
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);
30 } catch (remote::protocols::MMSException e
) {
31 Log::error("Exception: %s", e
.what());
33 Log::error("Disconnected");
36 Log::error("Connection failed");
39 Log::info("Reconnecting in %llu seconds...", secs
);
40 usleep(secs
* 1000000);
44 void MoteHost::serviceLoop()
46 std::string eventPipe
= config
.vm
["usbPlugEventPipe"].as
<std::string
>();
50 remove(eventPipe
.c_str());
51 if (mkfifo(eventPipe
.c_str(), 666) == -1) {
52 std::string err
= "Failed to make fifo " + eventPipe
+ ": " + strerror(errno
);
53 __THROW__ (err
.c_str());
56 plugpipe
= open(eventPipe
.c_str(), O_RDONLY
| O_NONBLOCK
);
58 std::string err
= "Failed to open fifo " + eventPipe
+ ": " + strerror(errno
);
59 __THROW__ (err
.c_str());
62 // the first thing to do is send all current mote information to the server
63 devices
.refresh(config
.vm
["devicePath"].as
<std::string
>());
64 Log::debug("Sending mote list to server");
65 MsgPlugEvent
msgPlugEvent(PLUG_MOTES
);
66 if (makeMoteInfoList(devices
.motes
, msgPlugEvent
.getInfoList())) {
67 HostMsg
hostMsg(msgPlugEvent
);
69 msg
.sendMsg(clientsock
,hostMsg
);
72 Log::debug("Entering service loop");
74 int maxfd
= rebuildFdSet(fdset
);
76 // wait for non-blocking reads on the fds
77 res
= select(maxfd
+1, &fdset
, NULL
, NULL
, NULL
);
81 if (FD_ISSET(clientsock
,&fdset
))
86 if (FD_ISSET(plugpipe
,&fdset
))
91 motemap_t::const_iterator moteI
= devices
.motes
.begin();
93 while (moteI
!= devices
.motes
.end())
95 p
= moteI
->second
->getFd();
96 if (p
> 0 && FD_ISSET(p
,&fdset
))
98 handleMoteData(moteI
->second
);
107 int MoteHost::rebuildFdSet(fd_set
& fdset
)
112 motemap_t::const_iterator moteI
= devices
.motes
.begin();
114 // put in valid mote file descriptors
116 while (moteI
!= devices
.motes
.end())
118 pmote
= moteI
->second
;
120 if (p
> 0 && pmote
->isValid())
122 if (p
> maxp
) {maxp
= p
;}
128 // fd for the connected server
129 FD_SET(clientsock
, &fdset
);
130 if (clientsock
> maxp
) {maxp
= clientsock
;}
131 FD_SET(plugpipe
, &fdset
);
132 if (plugpipe
> maxp
) {maxp
= plugpipe
;}
136 void MoteHost::handlePlugEvent()
139 // for now, just assume that a plug event occured
143 Log::info("Handling plug event");
146 i
= read(plugpipe
,&c
,1);
150 plugpipe
= open(config
.vm
["usbPlugEventPipe"].as
<std::string
>().c_str(),O_RDONLY
| O_NONBLOCK
);
154 devices
.refresh(config
.vm
["devicePath"].as
<std::string
>());
156 MsgPlugEvent
msgUnplugEvent(UNPLUG_MOTES
);
157 if (makeMoteInfoList(devices
.lostMotes
, msgUnplugEvent
.getInfoList()))
159 HostMsg
hostMsg(msgUnplugEvent
);
160 msg
.sendMsg(clientsock
,hostMsg
);
163 MsgPlugEvent
msgPlugEvent(PLUG_MOTES
);
164 if (makeMoteInfoList(devices
.newMotes
,msgPlugEvent
.getInfoList()))
166 HostMsg
hostMsg(msgPlugEvent
);
167 msg
.sendMsg(clientsock
,hostMsg
);
171 bool MoteHost::makeMoteInfoList(motemap_t
& motelist
, MsgMoteConnectionInfoList
& infolist
)
173 motemap_t::const_iterator moteI
;
177 for (moteI
= motelist
.begin(); moteI
!= motelist
.end(); moteI
++) {
178 Mote
*mote
= moteI
->second
;
179 MsgMoteConnectionInfo
info(mote
->getMac(), mote
->getDevicePath(),
180 mote
->getPlatform());
182 infolist
.addMoteInfo(info
);
185 return motelist
.size() > 0 ? true : false;
189 void MoteHost::handleMessage()
191 motemap_t::const_iterator moteI
;
194 if (msg
.nonBlockingRecv(clientsock
))
196 uint8_t* buffer
= msg
.getData();
197 uint32_t buflen
= msg
.getLength();
198 HostMsg
hostMsg(buffer
,buflen
);
200 if (hostMsg
.getType() != HOSTMSGTYPE_HOSTREQUEST
)
202 __THROW__ ("Can only handle hostmote messages!");
204 MsgHostRequest
& msgHostRequest
= hostMsg
.getHostRequest();
205 MsgMoteAddresses
& addresses
= msgHostRequest
.getMoteAddresses();
206 buffer
= (uint8_t*)msgHostRequest
.getMessage().getData();
207 buflen
= msgHostRequest
.getMessage().getDataLength();
208 MoteMsg
moteMsg(buffer
,buflen
);
210 moteI
= devices
.motes
.find(addresses
.getMac());
212 if (moteI
== devices
.motes
.end())
214 Log::warn("Mote %s unknown!", addresses
.getMac().c_str());
215 MsgHostConfirm
msgHostConfirm(MSGHOSTCONFIRM_UNKNOWN_MOTE
,addresses
,msgHostRequest
.getMessage());
216 HostMsg
msgReply(msgHostConfirm
);
217 msg
.sendMsg(clientsock
,msgReply
);
221 mote
= moteI
->second
;
223 switch (moteMsg
.getType()) {
224 case MOTEMSGTYPE_REQUEST
:
225 handleRequest(mote
,addresses
,moteMsg
.getRequest());
227 case MOTEMSGTYPE_DATA
:
229 MsgPayload payload
= moteMsg
.getData();
230 mote
->writeBuf((const char*)payload
.getData(),payload
.getDataLength());
234 __THROW__ ("Invalid message type!");
239 void MoteHost::handleRequest(Mote
* mote
, MsgMoteAddresses
& addresses
, MsgRequest
& request
)
241 uint8_t command
= request
.getCommand();
244 Log::debug("Mote %s got command=%u", addresses
.getMac().c_str(), command
);
248 case MOTECOMMAND_PROGRAM
:
249 result
= program(mote
, addresses
, request
.getFlashImage());
250 // don't confirm until programming is done
251 if (result
== SUCCESS
)
254 case MOTECOMMAND_CANCELPROGRAMMING
:
255 Log::info("User cancelling programming");
256 result
= mote
->cancelProgramming();
258 case MOTECOMMAND_STATUS
:
261 case MOTECOMMAND_RESET
:
262 result
= mote
->reset();
264 case MOTECOMMAND_START
:
265 result
= mote
->start();
267 case MOTECOMMAND_STOP
:
268 result
= mote
->stop();
271 Log::error("Unkown command %u", command
);
276 MsgConfirm
msgConfirm(command
, result
, mote
->getStatus());
277 MoteMsg
moteMsg(msgConfirm
);
278 MsgPayload
msgPayload(moteMsg
);
279 MsgHostConfirm
msgHostConfirm(MSGHOSTCONFIRM_OK
,addresses
,msgPayload
);
280 HostMsg
hostMsg(msgHostConfirm
);
282 msg
.sendMsg(clientsock
,hostMsg
);
286 void MoteHost::handleMoteData(Mote
* mote
)
289 ssize_t readlen
= sizeof(buf
);
291 MsgMoteAddresses
msgMoteAddresses(mote
->getMac());
293 while (readlen
== sizeof(buf
)) {
294 readlen
= mote
->readBuf(buf
, sizeof(buf
));
296 Log::debug("'%.*s'", readlen
, buf
);
297 uint32_t len
= readlen
;
299 msgData
.setPayload(len
,(uint8_t*)buf
);
300 MoteMsg
moteMsg(msgData
);
301 MsgPayload
msgPayload(moteMsg
);
302 MsgHostConfirm
msgHostConfirm(MSGHOSTCONFIRM_OK
,msgMoteAddresses
,msgPayload
);
303 HostMsg
hostMsg(msgHostConfirm
);
305 msg
.sendMsg(clientsock
,hostMsg
);
309 // check if we're done programming
312 result_t result
= mote
->getChildResult();
314 if (result
!= NOT_SUPPORTED
) {
315 Log::info("Programming done!");
316 remove(mote
->getImagePath().c_str());
317 MsgConfirm
msgConfirm(MOTECOMMAND_PROGRAM
, result
, mote
->getStatus());
318 MoteMsg
moteMsg(msgConfirm
);
319 MsgPayload
msgPayload(moteMsg
);
320 MsgHostConfirm
msgHostConfirm(MSGHOSTCONFIRM_OK
,msgMoteAddresses
,msgPayload
);
321 HostMsg
hostMsg(msgHostConfirm
);
323 msg
.sendMsg(clientsock
,hostMsg
);
325 Log::info("Invalidating mote '%s'", mote
->getMac().c_str());
332 result_t
MoteHost::program(Mote
*mote
, MsgMoteAddresses
& addresses
, MsgPayload
& image
)
334 std::string filename
= mote
->getImagePath();
336 if (mote
->getStatus() == MOTE_PROGRAMMING
)
339 if (File::writeFile(filename
, image
.getData(), image
.getDataLength())) {
340 std::string mac_env
= "macaddress=" + mote
->getMac();
341 std::string tos_env
= "tosaddress=" + addresses
.getTosAddress();
342 char * const args
[] = {
343 (char *) mote
->getProgrammerPath().c_str(),
344 (char *) mote
->getTty().c_str(),
345 (char *) filename
.c_str(),
348 char * const envp
[] = {
349 (char *) mac_env
.c_str(),
350 (char *) tos_env
.c_str(),
354 Log::info("Programming TTY %s", mote
->getTty().c_str());
356 if (mote
->runChild(args
, envp
))
359 remove(filename
.c_str());
366 int MoteHost::main(int argc
,char** argv
)
368 config
.read(argc
,argv
);
369 Log::open("diku_mch", LOG_INFO
);
370 if (config
.vm
["daemonize"].as
<int>()) {
373 Log::error("Failed to fork daemon");
380 Log::info("Running as daemon");
389 MoteHost::lookForServer();
395 int main(int argc
,char** argv
)
397 return remote::diku_mch::MoteHost::main(argc
,argv
);