Referring to the big picture shown here, the pseudo-code for the drivers, client (both running on the sensing nodes either fixed or mobile), server node (on CentMesh nodes) and controller (located behind the gateway) are shown below:
Driver
while(TRUE){
// in this section we take a measurement and ship it to the client process
read sample (for example from A/D converter, autopilot, GPS receiver, file etc);
form UDP datagram encapsulating the sample
send UDP datagram to socket SENSING_PORT; // this packet goes to the Client
// in this section we receive commands from the client (e.g., set some parameter for the device, or sensing period)
timeout = false;
remainingTimeoutTime = SENSING_PERIOD; // sensor period is specific to this sensor
do{
receive from UDP SENSING _PORT with timeout of remainingTimeoutTime seconds
if packet_received // packet received before timeout
process_packet();
update remainingTimeoutTime;
else // timeout before receiving packet
timeout = true;
}until (! timeout)
}
Client
SET_EXPECTED_SEQ = 0;
GET_NEXT_SEQ = 0;
while(TRUE){
if currentTime() - lastTimeAHeartbeatWasSent > HEARTBEAT_PERIOD {
send_heartbeat(); // This broadcasts a heartbeat to be received by server(s).
lastTimeAHeartbeatWasSent = curentTime();
}
// This part receives commands from the server
receive from UDP server port (SERVER_PORT) with a short timeout (1s)
if packet_received // packet received before timeout
if the packet is a SET & SEQ == EXPECTED_SEQ{
processSET();
SET_EXPECTED_SEQ++
}
else if the packet is a GET_ACK && GET_NEXT_SEQ {
remove top packet from queue
GET_NEXT_SEQ ++
}
// This part reads the samples from the drivers and enqueues them
timeout = false;
do{
receive from UDP driver port (SENSING_PORT) with a very short timeout (e.g., 0.1 seconds)
if packet_received // packet received before timeout
enqueue_reading_in_a_circular queue();
else // timeout before receiving packet
timeout = true;
}until (! timeout)
// Finally, try to send packet from the top of the queue
if (queue_not_empty)
send_top_packet_from_queue(GET_NEXT_SEQ);
}
If the programming language supports it, both UDP ports (SENSING_PORT and SERVER_PORT) should be read simultaneously (e.g., via select).
Server
while(TRUE)
receive packet from UDP port (SERVER_PORT);
if it is a measurement (GET), processMeasurement(receivedPacket);
elseif it is a command (SET), enqueue command in command queue;
elseif it is a command cancel (SETCANCEL), dequeue command (if found in the queue - can be more than one instance)
elseif it is a SET_ACK, dequeue conmmand and send ACK to the controller.
processCommandQueue();
}
processMeasurement(receivedPacket){
send measurement to central controller // if unreliable backhaul, then use a thread and ACKs. TCP may be the way to go on backhaul
send GET_ACK back to the client
}
processCommandQueue(){
// single threaded version - tries all packets one after the others
iterate through packets in the queue{
result = send_packet_with_ACK(currentPacket, RETRIES)
if result = SUCCESS
delete command from command queue
}
}
// just a stop and wait with a few retries
result = send_packet_with_ACK (datagram, retries){
while(retries-- > 0){
send_datagram_to_server(SERVER_PORT);
receive_ACK_from_server(timeout = 200ms);
if (ACK received)
return SUCCESSFUL;
}
return TIMEOUT;
}
Controller
while(TRUE){
receive measurement()
if old measurement (node id, sequence number)
continue;
else // if new measurement
storeMeasurement()
receiveCommand() // from port/keyboard/etc/
send command to all servers
when receiving ack from at least one server send cancel command to all servers
}
Last modified 17 months ago
Last modified on Jul 14, 2014, 9:35:10 PM
