/*----------------------------------------------------------------------------------------------------------------
* CupCarbon: A Smart City & IoT Wireless Sensor Network Simulator
* www.cupcarbon.com
* ----------------------------------------------------------------------------------------------------------------
* Copyright (C) 2013-2017 CupCarbon
* ----------------------------------------------------------------------------------------------------------------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*----------------------------------------------------------------------------------------------------------------
* CupCarbon U-One is part of the research project PERSEPTEUR supported by the
* French Agence Nationale de la Recherche ANR
* under the reference ANR-14-CE24-0017-01.
* ----------------------------------------------------------------------------------------------------------------
* Definition:
* This class allows to send messages by a sensor
*
* Command examples:
* send A 4
* -> The current sensor will send a message "A" to the sensor having an id = 4
* send A
* -> The current sensor will send a message "A" in a broadcast
* send A *
* -> The same than send A
* send A * 3
* -> The current sensor will send a message "A" in a broadcast mode except for the sensor having an id = 3
* ----------------------------------------------------------------------------------------------------------------
**/
package senscript;
import arduino.Arduino;
import device.Channels;
import device.DeviceList;
import device.MultiChannels;
import device.SensorNode;
import radio_module.RadioPacketGenerator;
import utilities.UColor;
import wisen_simulation.SimLog;
import wisen_simulation.SimulationInputs;
/**
* @author Ahcene Bounceur
*
*/
public class Command_SEND extends Command {
protected String arg1 = "";
protected String arg2 = "";
protected String arg3 = "";
protected String arg4 = "";
protected String arg5 = "";
protected String rRadioName = "";
protected boolean checkForAckMessage = false;
// ---------------------------------------------------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------------------------------------------------
public Command_SEND(SensorNode sensor, String arg1, String arg2) {
this.sensor = sensor ;
this.arg1 = arg1 ;
this.arg2 = arg2.split(":")[0] ;
if(arg2.split(":").length>1)
rRadioName = arg2.split(":")[1] ;
writtenInUART = false ;
}
// ---------------------------------------------------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------------------------------------------------
public Command_SEND(SensorNode sensor, String arg1, String arg2, String arg3) {
this.sensor = sensor ;
this.arg1 = arg1 ;
this.arg2 = arg2 ;
this.arg3 = arg3 ;
writtenInUART = false ;
}
// ---------------------------------------------------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------------------------------------------------
public Command_SEND(SensorNode sensor, String arg1, String arg2, String arg3, String arg4) {
this.sensor = sensor ;
this.arg1 = arg1 ;
this.arg2 = arg2 ;
this.arg3 = arg3 ;
this.arg4 = arg4 ;
writtenInUART = false ;
}
// ---------------------------------------------------------------------------------------------------------------------
// execute send
// First we write in a UART (if writtenInUART=false)
// Then the message will be sent by radio (if writtenInUART=true)
// Than we will wait for an ACK if this mode is activated (ie. SimulationInputs.ack=true)
// No ACK for the broadcast sending : arg2.equals("*") && arg3.equals("")
// ---------------------------------------------------------------------------------------------------------------------
@Override
public double execute() {
if(sensor.getScript().getVariableValue(arg1)==null || sensor.getScript().getVariableValue(arg2)==null) {
return 0;
}
//System.out.println("===================================");
//System.out.println(" CALL " + sensor.getId()+" "+sensor.ackOk());
//System.out.println("===================================");
if (arg1.equals("!color")) {
Double v = Double.parseDouble(sensor.getScript().getVariableValue(arg2));
sensor.setRadioLinkColor(UColor.colorTab2[v.intValue()]);
return 0;
}
String message = arg1;
message = sensor.getScript().getVariableValue(message);
int messageLength = message.length();
// In ACK mode (SimulationInputs.ack = true)
// After sending a message (ackBlock = true), we verify if the ASK message is received (sensor.ackOk)
// Otherwise, we recend the message
if(SimulationInputs.ack && checkForAckMessage) {
//System.out.println("ACK BLOCK");
if(sensor.isAckReceived()) {
//System.out.println(WisenSimulation.time + " ACK RECEIVED");
sensor.setAckReceived(false);
sensor.setAckWaiting(false);
sensor.setAttempts(0);
writtenInUART = false;
executing = false;
checkForAckMessage = false;
return 0 ;
}
else {
//System.out.println("RESEND");
sensor.incAttempts();
writtenInUART = true;
}
}
// First operation, we start by writing the message in the UART of the card
if(!writtenInUART) {
//System.out.println("UART");
sensor.setMessageLost(false);
sensor.setAckReceived(false);
sensor.setAttempts(0);
SimLog.add("S" + sensor.getId() + " is writing the message : \"" + message + "\" in its buffer.");
writtenInUART = true ;
executing = true;
double ratio = 1.0/(sensor.getUartDataRate());
return (ratio * (messageLength*8)) ;
}
//System.out.println(writtenInUART+ " "+sensor.ackOk() +" " + sensor.getAttempts() + " " + sensor.getNumberOfSends() );
// ---------------------------------------------------------------------------------------------------------------------
// Once the message is written in the UART, here we send it without ack if :
// Non ACK mode (!SimulationInputs.ack)
// or in a broadcast mode (send x *)
// ---------------------------------------------------------------------------------------------------------------------
if (writtenInUART && (!SimulationInputs.ack || (arg2.equals("*") && arg3.equals("")))) {
SimLog.add("S" + sensor.getId() + " starts sending the message : \"" + message + "\".");
//System.out.println(WisenSimulation.time + " SEND " + message);
//System.out.println("SEND");
sensor.setAckReceived(false);
sensor.setAckWaiting(false);
writtenInUART = false;
executing = false;
sensor.setAttempts(0);
sendOperation(message);
return 0;
}
// ---------------------------------------------------------------------------------------------------------------------
// Once the message is written in the UART, here we send it with ack mode
// ---------------------------------------------------------------------------------------------------------------------
if (writtenInUART && SimulationInputs.ack && !sensor.isAckWaiting()) {
//if (writtenInUART && SimulationInputs.ack) {
if(sensor.getAttempts() < sensor.getNumberOfSends()) {
SimLog.add("S" + sensor.getId() + " starts sending the message : \"" + message + "\".");
//System.out.println(WisenSimulation.time+ " "+ sensor.getAttempts() + " SEND " + message);
sensor.setAckWaiting(true);
//System.out.println();
sendOperation(message);
checkForAckMessage = true;
return sensor.getTimeToResend();
}
else {
Channels.numberOfLostMessages++;
//System.out.println("MESSAGE LOST");
sensor.setAckWaiting(false);
checkForAckMessage = false;
sensor.setAckReceived(false);
writtenInUART = false;
executing = false;
sensor.setAttempts(0);
sensor.setMessageLost(true);
return 0;
}
}
return 0;
}
// ---------------------------------------------------------------------------------------------------------------------
// Generate Arduino Code for the SEND function
// ---------------------------------------------------------------------------------------------------------------------
//@Override
// public String getArduinoForm2() {
// String s1 = sensor.getScript().getVariableValue(arg1);
// String s2 = sensor.getScript().getVariableValue(arg2);
// String s3 = sensor.getScript().getVariableValue(arg3);
// System.out.println(arg1);
// System.out.println(arg2);
// System.out.println(arg3);
// System.out.println(s1);
// System.out.println(s2);
// System.out.println(s3);
// String s = XBeeToArduinoFrameGenerator.data16(s1, s2, s3);
// return s;
// }
@Override
public String getArduinoForm() {
String s = "";
if(arg1.charAt(0)=='$') {
s += "\tfor(int i=0; i<30; i++) {\n";
s += "\t\tsdata[i] = " + arg1.substring(1) + ".charAt(i);\n";
s += "\t}\n";
}
else {
for(int i=0; i<arg1.length();i++) {
s += "\tsdata["+ i +"] = '" + arg1.charAt(i) + "';\n";
}
s +="\tfor(int i="+arg1.length()+"; i < 30; i++) {\n";
s +="\t\tsdata[i] = ' ';\n\t}\n";
}
String [] info ;
if (arg2.equals("") || arg2.equals("*")) {
s += "\taddr = XBeeAddress64(0x0, 0xFFFF);\n";
}
else
if (arg2.equals("0")) {
info = getXBeeInfoById(arg2);
s += "\taddr = XBeeAddress16(0x0, "+info[1]+");\n";
}
else {
info = getXBeeInfoById(arg2);
s += "\taddr = XBeeAddress64("+info[2]+", "+info[3]+");\n";
}
s += "\ttx = Tx64Request(addr, sdata, sizeof(sdata));\n";
s += "\txbee.send(tx);";
return s;
}
public String [] getXBeeInfoById(String id) {
String [] info = {"", "", "", ""};
for(String [] s : Arduino.xbeeList) {
if(s[0].equals(id)) {
info[0] = s[1];
info[1] = s[2];
info[2] = s[3];
info[3] = s[4];
}
}
// for(int i=0; i<5; i++) {
// if(Arduino.xbeeList.get(i)[0].equals(id)) {
// info[0] = Arduino.xbeeList.get(i)[1];
// info[1] = Arduino.xbeeList.get(i)[2];
// info[2] = Arduino.xbeeList.get(i)[3];
// info[3] = Arduino.xbeeList.get(i)[4];
// }
// }
return info;
}
// ---------------------------------------------------------------------------------------------------------------------
// toString()
// ---------------------------------------------------------------------------------------------------------------------
@Override
public String toString() {
if(writtenInUART)
return "SEND [BY RADIO]";
else
return "SEND [TO UART]";
}
// ---------------------------------------------------------------------------------------------------------------------
// Operation of sending a message (prepare the packets according to the standard and the type of the command)
// Calculate the energy consumption of the sending ooperation
// ---------------------------------------------------------------------------------------------------------------------
public void sendOperation(String message) {
//String packet = RadioPacketGenerator.generate(sensor.getStandard());
Channels.numberOfSentMessages++;
sensor.consumeTx(RadioPacketGenerator.packetLengthInBits(0, sensor.getStandard()));
if (arg2.equals("*")) {
SimLog.add("S" + sensor.getId() + " has finished sending in a broadcast the message : \"" + message + "\" to the nodes: ");
double v = 0;
if (!arg3.equals("")) {
v = Double.valueOf(sensor.getScript().getVariableValue(arg3));
}
for (SensorNode rnode : sensor.getSensorNodeNeighbors()) {
if (sensor.propagationDetect(rnode) && sensor.canCommunicateWith(rnode) && rnode.getId()!=v) {
MultiChannels.addPacketEvent(2, message, sensor, rnode);
}
}
}
else {
String dest = arg2;
dest = sensor.getScript().getVariableValue(dest);
double destNodeId;
if(!dest.equals("0")) {
destNodeId = Double.valueOf(dest);
SensorNode rnode = DeviceList.getSensorNodeById((int) destNodeId);
if (rnode != null) {
SimLog.add("S" + sensor.getId() + " has finished sending the message : \"" + message + "\" to the node: ");
if (sensor.propagationDetect(rnode) && sensor.canCommunicateWith(rnode)) {
if(rRadioName.equals("") || rRadioName.equals(rnode.getCurrentRadioModule().getName()))
MultiChannels.addPacketEvent(0, message, sensor, rnode);
}
else
SimLog.add("S" + sensor.getId() + " and S" + destNodeId + "have not the same protocol!");
}
else
SimLog.add("S" + sensor.getId() + " can not send the message : \"" + message + "\" to the non-existent node: "+destNodeId);
}
else {
dest = arg3;
dest = sensor.getScript().getVariableValue(dest);
destNodeId = Double.valueOf(dest);
if(!dest.equals("0")) {
SimLog.add("S" + sensor.getId() + " has finished sending the message : \"" + message + "\" to the nodes with MY="+destNodeId+": ");
for(SensorNode rnode : DeviceList.sensors) {
if ((sensor.propagationDetect(rnode)) && (rnode.getCurrentRadioModule().getMy()==destNodeId) && sensor.canCommunicateWith(rnode)) {
SimLog.add(" -> S" + rnode.getId() + " ");
//rnode.setReceiving(true);
MultiChannels.addPacketEvent(0, message, sensor, rnode);
}
}
}
else {
dest = arg4;
dest = sensor.getScript().getVariableValue(dest);
if(!dest.equals("0")) {
destNodeId = Integer.valueOf(dest);
SensorNode rnode = DeviceList.getSensorNodeById((int)destNodeId);
if (rnode != null) {
SimLog.add("S" + sensor.getId() + " has finished sending the message : \"" + message + "\" to the node: ");
if (sensor.canCommunicateWith(rnode)) {
MultiChannels.addPacketEvent(0, message, sensor, rnode);
}
}
else
SimLog.add("S" + sensor.getId() + " can not send the message : \"" + message + "\" to the non-existent node: "+destNodeId);
}
}
}
}
}
}