diff --git a/jdeeco-core/model/RuntimeModel.ecore b/jdeeco-core/model/RuntimeModel.ecore index 7ebece4fc..b82514f2d 100644 --- a/jdeeco-core/model/RuntimeModel.ecore +++ b/jdeeco-core/model/RuntimeModel.ecore @@ -44,7 +44,7 @@ + eType="#//ObjectToObjectMap" containment="true"/> @@ -96,8 +96,8 @@ - - + + diff --git a/jdeeco-core/model/RuntimeModel.ecorediag b/jdeeco-core/model/RuntimeModel.ecorediag index 3c13cb685..a30f1a34a 100644 --- a/jdeeco-core/model/RuntimeModel.ecorediag +++ b/jdeeco-core/model/RuntimeModel.ecorediag @@ -404,11 +404,11 @@ - + - + @@ -421,7 +421,7 @@ - + diff --git a/jdeeco-core/model/RuntimeModel.genmodel b/jdeeco-core/model/RuntimeModel.genmodel index 87913a354..dd5d99e38 100644 --- a/jdeeco-core/model/RuntimeModel.genmodel +++ b/jdeeco-core/model/RuntimeModel.genmodel @@ -16,9 +16,11 @@ - - - + + + + + @@ -42,14 +44,16 @@ - + + + @@ -62,6 +66,7 @@ + @@ -74,5 +79,9 @@ + + + + diff --git a/jdeeco-core/plugin.xml b/jdeeco-core/plugin.xml index 8b0779b75..6094797c1 100644 --- a/jdeeco-core/plugin.xml +++ b/jdeeco-core/plugin.xml @@ -9,8 +9,8 @@ diff --git a/jdeeco-core/pom.xml b/jdeeco-core/pom.xml index 4811e3385..fb8dcb4a7 100644 --- a/jdeeco-core/pom.xml +++ b/jdeeco-core/pom.xml @@ -10,12 +10,6 @@ cz.cuni.mff.d3s.jdeeco.core jar - ../dist - jdeeco.jar - ${dist}/lib - cloner.jar - objenesis.jar - UTF-8 src @@ -35,92 +29,7 @@ - - org.apache.maven.plugins - maven-dependency-plugin - 2.6 - - - copy - install - - copy - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - ${project.packaging} - ${coreJar} - ${dist} - - - - - - install - - copy-dependencies - - - ${dist} - compile - - - - - - maven-clean-plugin - 2.5 - - - clean-dist - - clean - - clean - - true - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [1.0.0,) - - unpack - - copy-dependencies - - - - - - - - - - - - - diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java index 7fce302a0..c66d3a30d 100644 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java +++ b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/Host.java @@ -19,7 +19,6 @@ public class Host implements CurrentTimeProvider, NetworkInterface { private final NetworkProvider networkProvider; private final CurrentTimeProvider timeProvider; - protected Host(NetworkProvider networkProvider, CurrentTimeProvider timeProvider, String jDEECoAppModuleId, boolean hasMANETNic, boolean hasIPNic) { this.networkProvider = networkProvider; this.timeProvider = timeProvider; diff --git a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PositionProvider.java b/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PositionProvider.java deleted file mode 100644 index ed758a1a9..000000000 --- a/jdeeco-core/src/cz/cuni/mff/d3s/deeco/network/PositionProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package cz.cuni.mff.d3s.deeco.network; - -public interface PositionProvider { - public boolean isPositionSensorAvailable(Host host); - public double getPositionX(Host host); - public double getPositionY(Host host); - public double getPositionZ(Host host); -} diff --git a/jdeeco-parent/pom.xml b/jdeeco-parent/pom.xml index 1d9685923..8bd2fe7c8 100644 --- a/jdeeco-parent/pom.xml +++ b/jdeeco-parent/pom.xml @@ -6,28 +6,14 @@ pom cz.cuni.mff.d3s.jdeeco - ../dist - ../jdeeco-core/src - default + UTF-8 - - - default - - true - - - default - - - ../jdeeco-core - ../jdeeco-demo - ../jdeeco-core-osgi - ../jdeeco-simulation - ../jdeeco-simulation-demo - - - + + ../jdeeco-core + + ../jdeeco-simulation + + @@ -38,33 +24,46 @@ 1.7 1.7 - - - maven-clean-plugin - 2.5 - - - clean-dist - - clean - - clean - - - - ${dist} - - - - - + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + [1.0.0,) + + unpack + + copy-dependencies + + + + + + + + + + + + + - + - sonatype.releases - http://oss.sonatype.org/content/repositories/releases/ - + sonatype.releases + http://oss.sonatype.org/content/repositories/releases/ + \ No newline at end of file diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java index af33dca19..e00d75ce8 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Main.java @@ -20,6 +20,7 @@ import cz.cuni.mff.d3s.deeco.annotations.processor.AnnotationProcessor; import cz.cuni.mff.d3s.deeco.annotations.processor.AnnotationProcessorException; import cz.cuni.mff.d3s.deeco.logging.Log; +import cz.cuni.mff.d3s.deeco.model.runtime.api.ComponentInstance; import cz.cuni.mff.d3s.deeco.model.runtime.api.RuntimeMetadata; import cz.cuni.mff.d3s.deeco.model.runtime.custom.RuntimeMetadataFactoryExt; import cz.cuni.mff.d3s.deeco.network.DirectGossipStrategy; @@ -30,8 +31,8 @@ import cz.cuni.mff.d3s.deeco.network.PublisherTask; import cz.cuni.mff.d3s.deeco.runtime.RuntimeFramework; import cz.cuni.mff.d3s.deeco.simulation.SimulationHost; +import cz.cuni.mff.d3s.deeco.simulation.SimulationRuntimeBuilder; import cz.cuni.mff.d3s.deeco.simulation.omnet.OMNetSimulation; -import cz.cuni.mff.d3s.deeco.simulation.omnet.OMNetSimulationRuntimeBuilder; /** * Main class for launching the CBSE evaluation demo. @@ -65,7 +66,7 @@ public static void main(String[] args) throws AnnotationProcessorException, IOEx OMNetSimulation sim = new OMNetSimulation(); AnnotationProcessor processor = new AnnotationProcessor(RuntimeMetadataFactoryExt.eINSTANCE); - OMNetSimulationRuntimeBuilder builder = new OMNetSimulationRuntimeBuilder(); + SimulationRuntimeBuilder builder = new SimulationRuntimeBuilder(); SiteConfigParser siteParser = new SiteConfigParser(siteCfg); Position topRight = siteParser.parseTopRightCorner(); @@ -143,7 +144,9 @@ public Collection filterRecipients( AreaNetworkRegistry.INSTANCE.addComponent(component); // there is only one component instance - model.getComponentInstances().get(0).getInternalData().put(PositionAwareComponent.HOST_REFERENCE, host); + for (ComponentInstance ci: model.getComponentInstances()) { + PositionAwareComponent.initialize(ci, new PositionSensor(host, sim)); + } Collection recipientSelectors = null; if (component.hasIP) { recipientSelectors = Arrays.asList((DirectRecipientSelector) directRecipientSelector); diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Member.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Member.java index 301edeaa8..0ba0b4b40 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Member.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/Member.java @@ -18,14 +18,12 @@ import java.util.Map; import java.util.Random; -import cz.cuni.mff.d3s.deeco.DeecoProperties; import cz.cuni.mff.d3s.deeco.annotations.In; import cz.cuni.mff.d3s.deeco.annotations.Out; import cz.cuni.mff.d3s.deeco.annotations.PeriodicScheduling; import cz.cuni.mff.d3s.deeco.annotations.Process; import cz.cuni.mff.d3s.deeco.annotations.Component; import cz.cuni.mff.d3s.deeco.logging.Log; -import cz.cuni.mff.d3s.deeco.network.PublisherTask; import cz.cuni.mff.d3s.deeco.task.ParamHolder; import cz.cuni.mff.d3s.deeco.task.ProcessContext; @@ -55,7 +53,7 @@ public Member(String id, String team_id, Position position, boolean hasIP) { @PeriodicScheduling(500) public static void measureMemberData(@In("id") String id, @Out("memberData") ParamHolder memberData) { - Map internal = ProcessContext.getCurrentProcess().getComponentInstance().getInternalData().map(); + Map internal = ProcessContext.getCurrentProcess().getComponentInstance().getInternalData().map(); if (!internal.containsKey(DANGER_TIME)) { long seed = 0; for (char c: id.toCharArray()) diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionAwareComponent.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionAwareComponent.java index 02f07bcbc..fda9b840c 100644 --- a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionAwareComponent.java +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionAwareComponent.java @@ -4,7 +4,7 @@ import cz.cuni.mff.d3s.deeco.annotations.InOut; import cz.cuni.mff.d3s.deeco.annotations.PeriodicScheduling; import cz.cuni.mff.d3s.deeco.annotations.Process; -import cz.cuni.mff.d3s.deeco.network.Host; +import cz.cuni.mff.d3s.deeco.model.runtime.api.ComponentInstance; import cz.cuni.mff.d3s.deeco.task.ParamHolder; import cz.cuni.mff.d3s.deeco.task.ProcessContext; @@ -13,7 +13,7 @@ public class PositionAwareComponent { public Position position; public boolean hasIP; - public static String HOST_REFERENCE = "simulation.host"; + public static String POSITION_SENSOR = "gps"; public PositionAwareComponent(String id, Position position, boolean hasIP) { this.id = id; @@ -21,14 +21,17 @@ public PositionAwareComponent(String id, Position position, boolean hasIP) { this.hasIP = hasIP; } + public static void initialize(ComponentInstance componentInstance, PositionSensor positionSensor) { + componentInstance.getInternalData().put(POSITION_SENSOR, positionSensor); + } @Process @PeriodicScheduling(500) public static void measurePosition( @InOut("position") ParamHolder position) { - Host host = (Host) ProcessContext.getCurrentProcess().getComponentInstance().getInternalData().get(HOST_REFERENCE); - if (host != null) { - position.value = new Position(host.getPositionX(), host.getPositionY()); + PositionSensor sensor = (PositionSensor) ProcessContext.getInternalData(POSITION_SENSOR); + if (sensor != null) { + position.value = new Position(sensor.getX(), sensor.getY()); } } } diff --git a/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionSensor.java b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionSensor.java new file mode 100644 index 000000000..83f53eb65 --- /dev/null +++ b/jdeeco-simulation-demo/src/cz/cuni/mff/d3s/jdeeco/simulation/demo/PositionSensor.java @@ -0,0 +1,23 @@ +package cz.cuni.mff.d3s.jdeeco.simulation.demo; + +import cz.cuni.mff.d3s.deeco.network.Host; +import cz.cuni.mff.d3s.deeco.simulation.omnet.OMNetSimulation; + +public class PositionSensor { + + private final Host host; + private final OMNetSimulation simulation; + + public PositionSensor(Host host, OMNetSimulation simulation) { + this.host = host; + this.simulation = simulation; + } + + public double getX() { + return simulation.getPositionX(host); + } + + public double getY() { + return simulation.getPositionY(host); + } +} diff --git a/jdeeco-simulation-omnet-native/.project b/jdeeco-simulation-omnet-native/.project new file mode 100644 index 000000000..94a5a250f --- /dev/null +++ b/jdeeco-simulation-omnet-native/.project @@ -0,0 +1,17 @@ + + + cz.cuni.mff.d3s.jdeeco.simulation.omnet-native + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/jdeeco-simulation-omnet-native/.settings/org.eclipse.core.resources.prefs b/jdeeco-simulation-omnet-native/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..99f26c020 --- /dev/null +++ b/jdeeco-simulation-omnet-native/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/jdeeco-simulation-omnet-native/.settings/org.eclipse.m2e.core.prefs b/jdeeco-simulation-omnet-native/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 000000000..f897a7f1c --- /dev/null +++ b/jdeeco-simulation-omnet-native/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/jdeeco-simulation-omnet-native/Makefile b/jdeeco-simulation-omnet-native/Makefile new file mode 100644 index 000000000..5ea059090 --- /dev/null +++ b/jdeeco-simulation-omnet-native/Makefile @@ -0,0 +1,88 @@ +#JAVA_HOME ?= /usr/lib/jvm/java-7-openjdk-amd64 + +INET_DIR ?= ${OMNETPP_ROOT}/../inet +MIXIM_DIR ?= ${OMNETPP_ROOT}/../mixim-2.3 + +CONFIGFILE = $(shell opp_configfilepath) +include $(CONFIGFILE) + +all: checkmakefiles + cd src && $(MAKE) + +clean: checkmakefiles + cd src && $(MAKE) clean + +cleanall: checkmakefiles + cd src && $(MAKE) clean + rm -f src/Makefile + rm -rf out/ + +# Create makefiles that allows building mixim without a separate INET installation. +makefiles: + cd src && opp_makemake -f --deep --make-so -o jdeeco-omnetpp -O out \ + -I${JAVA_HOME}/include \ + -I${OMNETPP_SRC_DIR}/common -I${OMNETPP_INCL_DIR}/platdep -I${OMNETPP_SRC_DIR}/envir \ + -I${MIXIM_DIR}/src \ + -I${MIXIM_DIR}/src/base \ + -I${MIXIM_DIR}/src/base/modules \ + -I${MIXIM_DIR}/src/base/utils \ + -I${MIXIM_DIR}/src/base/connectionManager \ + -I${MIXIM_DIR}/src/base/phyLayer \ + -I${MIXIM_DIR}/src/base/messages \ + -I${INET_DIR}/src/linklayer/ieee80211/radio \ + -I${INET_DIR}/src/linklayer/ethernet \ + -I${INET_DIR}/src/networklayer/common \ + -I${INET_DIR}/src \ + -I${INET_DIR}/src/networklayer/icmpv6 \ + -I${INET_DIR}/src/world/obstacles \ + -I${INET_DIR}/src/networklayer/xmipv6 \ + -I${INET_DIR}/src/networklayer/manetrouting/base \ + -I${INET_DIR}/src/networklayer/contract \ + -I${INET_DIR}/src/mobility/models \ + -I${INET_DIR}/src/mobility \ + -I${INET_DIR}/src/networklayer/autorouting/ipv4 \ + -I${INET_DIR}/src/linklayer/ieee80211/mgmt \ + -I${INET_DIR}/src/util \ + -I${INET_DIR}/src/linklayer/common \ + -I${INET_DIR}/src/transport/contract \ + -I${INET_DIR}/src/status \ + -I${INET_DIR}/src/linklayer/radio/propagation \ + -I${INET_DIR}/src/linklayer/ieee80211/radio/errormodel \ + -I${INET_DIR}/src/linklayer/radio \ + -I${INET_DIR}/src/util/headerserializers/tcp \ + -I${INET_DIR}/src/networklayer/ipv4 \ + -I${INET_DIR}/src/util/headerserializers/ipv4 \ + -I${INET_DIR}/src/base \ + -I${INET_DIR}/src/util/headerserializers \ + -I${INET_DIR}/src/world/radio \ + -I${INET_DIR}/src/linklayer/ieee80211/mac \ + -I${INET_DIR}/src/networklayer/ipv6 \ + -I${INET_DIR}/src/transport/sctp \ + -I${INET_DIR}/src/util/headerserializers/udp \ + -I${INET_DIR}/src/networklayer/ipv6tunneling \ + -I${INET_DIR}/src/applications/pingapp \ + -I${INET_DIR}/src/battery/models \ + -I${INET_DIR}/src/util/headerserializers/sctp \ + -I${INET_DIR}/src/linklayer/contract \ + -I${INET_DIR}/src/networklayer/arp \ + -I${INET_DIR}/src/transport/tcp_common \ + -I${INET_DIR}/src/transport/udp \ + -I${INET_DIR}/src/mobility/static \ + -I${INET_DIR}/src/mobility/common \ + -I${INET_DIR}/src/mobility/contract \ + -L${MIXIM_DIR}/out/$(CONFIGNAME)/src \ + -L${INET_DIR}/out/$(CONFIGNAME)/src \ + -lmixim -linet -DMIXIM_INET=1 -DINET_IMPORT -KMIXIM_PROJ=${MIXIM_DIR} -KINET_PROJ=${INET_DIR} -KV=1 + + +checkmakefiles: makefiles +# @if [ ! -f src/Makefile ]; then \ + echo; \ + echo '=========================================================='; \ + echo 'src/Makefile does not exist. Please use "make makefiles"'; \ + echo 'to generate it!'; \ + echo '=========================================================='; \ + echo; \ + exit 1; \ + fi + diff --git a/jdeeco-simulation-omnet-native/README.md b/jdeeco-simulation-omnet-native/README.md new file mode 100644 index 000000000..802640ea3 --- /dev/null +++ b/jdeeco-simulation-omnet-native/README.md @@ -0,0 +1,14 @@ +This project is meant to provide the integration between jDEECo (Java) and the OMNET++ simulation framework (C++). +JNI is used in the implementation and as an output of the project a shared library is produced that provides native API for communicating with the simulation. + +#### Building the project (WINDOWS): +* In oreder to build and use the library the OMNET++ distribution needs to be rebuild with slightly modified configuration. The modified config.user file is in the "omnet-config" directory and needs to be placed in the root directory of the OMNET++ installation. Specifically it directs building process to statically link some of the libraries that may conflict with other libraries in the system. To rebuild the OMNET++ please follow the process described in the manual. +* Another part is to configure properly the eclipse project. The project requires includes that are provided by the OMNET++ and as such in the Project Properties > C\C++ General > Paths and Symbols > Includes please add path to the "include" directory in your OMNET++ installation. +* Similarly the project needs to be linked with the OMNET++ libraries so in the Project Properties > C\C++ General > Paths and Symbols > Library Paths please point to the "bin" directory of the OMNET++ project. Alternatively, if you did not rebuild the OMNET++ distribution (see the first bullet) you can use libraries given in the project. For that you need to set "Library paths" to project location ("."). In the "Libraries" tab please add following entries "oppsim", "oppenvir" and "oppcommon". + +#### Usage in OMNET++: +In order to connect the OMNET++ simulation with jDEECo, one needs to create a simple module that inherits (pure C++ inheritance, not in NED file) from the jDEECoModule class. Appropriate headers files can be found in the project so an inclusion pointing to the project location is necessary. Also the reference to the integration library is necessary and it needs to be set in the "Library paths" tab in the Project Properties > C\C++ General > Paths and Symbols to point also to this project location. +Because OMNET++ relies on the Makemake, setting up particular libraries reference is different than previously. For that one needs to open the Project Properties > OMNt++ > Makemake > [configuration] > Options > Link > More and in the "Additional libraries to link" put "integration". Also in the Project Properties > OMNt++ > Makemake > [configuration] > Options > Target tab please select shared library. This shared library will be loaded when jDEECo is run. However, this step should be done at the end of the development of the network topology. + +#### Usage with jDEECo: +To use the developed (in OMNet++) network topology one needs to provide all necessary libraries (i.e. main library + library used in the project such as iNET, Mixims, ....). All of them should be compiled in the relase mode so the correct libraries are loaded. Additionally, in the omnetpp.ini file please update the "load-libs" entry, which is the (white space separted) list of additional libraries that needs to be loaded for the simulation. diff --git a/jdeeco-simulation-omnet-native/models/CustomEthernetInterface.ned b/jdeeco-simulation-omnet-native/models/CustomEthernetInterface.ned new file mode 100644 index 000000000..d6ccd8735 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/CustomEthernetInterface.ned @@ -0,0 +1,150 @@ +// +// Copyright (C) 2004 Andras Varga +// 2010 Zoltan Bojthe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program; if not, see . +// + + + +package manet; + +import inet.base.IHook; +import inet.linklayer.IEtherMAC; +import inet.linklayer.ITrafficConditioner; +import inet.linklayer.IWiredNic; +import inet.linklayer.ethernet.EtherQoSQueue; +import inet.linklayer.ethernet.IEtherEncap; + + +// +// Ethernet network interface. Complements ~EtherMAC and ~EtherEncap +// with an output queue for QoS and RED support. +// +module CustomEthernetInterface like IWiredNic +{ + parameters: + bool csmacdSupport = default(false); // by default CSMA/CD is turned off, so only point-to-point duplex links are supported. + string macType = default(csmacdSupport ? "EtherMAC" : "EtherMACFullDuplex"); // ~EtherMAC or ~EtherMACFullDuplex + string queueType = default(""); // ~DropTailQueue, or a Diffserv queue; set to "" for use of an internal queue + string ingressTCType = default(""); // a module type implementing ~ITrafficConditioner for optional traffic conditioning of incoming traffic + string egressTCType = default(""); // a module type implementing ~ITrafficConditioner for optional traffic conditioning of outgoing traffic + string encapType = default("EtherEncap"); // module for encapsulation/decapsulation; use ~EtherEncapDummy for no encapsulation/decapsulation + int numOutputHooks = default(0); + int numInputHooks = default(0); + @display("i=block/ifcard;bgl=2"); + gates: + input upperLayerIn; + output upperLayerOut; + inout phys @labels(EtherFrame); + submodules: + outputHook[numOutputHooks]: like IHook if numOutputHooks>0 { + @display("p=80,98"); + } + inputHook[numInputHooks]: like IHook if numInputHooks>0 { + @display("p=265,83"); + } + ingressTC: like ITrafficConditioner if ingressTCType != "" { + @display("p=292,158"); + } + egressTC: like ITrafficConditioner if egressTCType != "" { + @display("p=53,158"); + } + queue: EtherQoSQueue if queueType != "" { + parameters: + dataQueueType = queueType; + @display("p=107,263;q=l2queue"); + } + mac: like IEtherMAC { + parameters: + queueModule = (queueType == "" ? "" : "queue"); + @display("p=182,321"); + } + encap: like IEtherEncap { + parameters: + @display("p=182,205"); + } + connections: + mac.upperLayerOut --> encap.lowerLayerIn; + mac.phys <--> { @display("m=s"); } <--> phys; + + if queueType != "" { + encap.lowerLayerOut --> queue.in ; + queue.out --> mac.upperLayerIn; + } + + encap.lowerLayerOut --> mac.upperLayerIn if queueType == ""; + + // no input hooks, no ingressTC + encap.upperLayerOut --> { @display("m=n"); } --> upperLayerOut if numInputHooks == 0 && ingressTCType == ""; + + // no input hooks, there is ingressTC + if numInputHooks == 0 && ingressTCType != "" { + encap.upperLayerOut --> ingressTC.in; + ingressTC.out --> { @display("m=n"); } --> upperLayerOut; + } + + // there are input hooks + if numInputHooks > 0 { + inputHook[numInputHooks-1].out --> { @display("m=n"); } --> upperLayerOut; + } + for i=0..numInputHooks-2 { + inputHook[i].out --> inputHook[i+1].in; + } + + // there are input hooks, no ingressTC + if numInputHooks > 0 && ingressTCType == "" { + encap.upperLayerOut --> inputHook[0].in; + } + + // there are input hooks, there is ingressTC + if numInputHooks > 0 && ingressTCType != "" { + encap.upperLayerOut --> ingressTC.in; + ingressTC.out --> inputHook[0].in; + } + + // chain output hooks + for i=0..numOutputHooks-2 { + outputHook[i].out --> outputHook[i+1].in; + } + + // no output hooks, no egressTC + upperLayerIn --> { @display("m=n"); } --> encap.upperLayerIn if numOutputHooks == 0 && egressTCType == ""; + + // there are output hooks + if numOutputHooks > 0 { + upperLayerIn --> { @display("m=n"); } --> outputHook[0].in; + } + + // no output hooks, there is egressTC + if numOutputHooks == 0 && egressTCType != "" { + upperLayerIn --> { @display("m=n"); } --> egressTC.in; + } + + // there is egressTC + if egressTCType != "" { + egressTC.out --> encap.upperLayerIn; + } + + // there are output hooks, no egressTC + if numOutputHooks > 0 && egressTCType == "" { + outputHook[numOutputHooks-1].out --> encap.upperLayerIn; + } + + // there are output hooks, there is egressTC + if numOutputHooks > 0 && egressTCType != "" { + outputHook[numInputHooks-1].out --> egressTC.in; + } +} + diff --git a/jdeeco-simulation-omnet-native/models/CustomMobility.ned b/jdeeco-simulation-omnet-native/models/CustomMobility.ned new file mode 100644 index 000000000..0e4cce901 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/CustomMobility.ned @@ -0,0 +1,25 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +package manet; + +import inet.mobility.models.StationaryMobility; +// +// TODO auto-generated module +// +simple CustomMobility extends StationaryMobility +{ + @class(CustomMobility); +} diff --git a/jdeeco-simulation-omnet-native/models/Host802154.ned b/jdeeco-simulation-omnet-native/models/Host802154.ned new file mode 100644 index 000000000..af819dcaf --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/Host802154.ned @@ -0,0 +1,11 @@ +package manet; + +import org.mixim.modules.node.WirelessNodeBatteryPlusTran; + +module Host802154 extends WirelessNodeBatteryPlusTran +{ + parameters: + arpType = "ArpHost"; + nicType = "Nic802154_TI_CC2420"; + transportType = "Aggregation"; +} diff --git a/jdeeco-simulation-omnet-native/models/JDEECoApplication.ned b/jdeeco-simulation-omnet-native/models/JDEECoApplication.ned new file mode 100644 index 000000000..96d5c6f86 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/JDEECoApplication.ned @@ -0,0 +1,42 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +package manet; +// +// TODO auto-generated module +// +simple JDEECoApplication +{ + parameters: + int headerLength = 0; + string id = default("not-assigned"); + int port = default(2222); + + int packet80211ByteLength @unit("B") = default(1000B); + int packet802154ByteLength @unit ("B") = default(1000B); + + //Google-Earth relevant paramters + string color = default(""); // the color of the trail and range indicator in hex BBGGRR format or "" for random color + string modelURL = default(""); // the URL of the 3D model (COLLADA file format) to be used for the node + double modelScale = default(1.0); // allows scaling of the used model + bool showTxRange = default(true); // whether to show the transmission range around the nodes + double txRange @unit("m") = default(250m); // the transmission range of the mobile node's radio + gates: + input lowerLayerIn; // from network layer + output lowerLayerOut; // to network layer + + input lower802154LayerIn; // from manet layer + output lower802154LayerOut; // to manet layer +} diff --git a/jdeeco-simulation-omnet-native/models/KmlHttpServer.ned b/jdeeco-simulation-omnet-native/models/KmlHttpServer.ned new file mode 100644 index 000000000..a61a4a6f0 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/KmlHttpServer.ned @@ -0,0 +1,24 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + + +// +// Answers HTTP GET requests that arrive to the built-in web server +// of the simulation, and returns KML or HTML documents. +// +package manet; + + +simple KmlHttpServer +{ + @display("i=block/socket"); +} + + + diff --git a/jdeeco-simulation-omnet-native/models/MANET.ned b/jdeeco-simulation-omnet-native/models/MANET.ned new file mode 100644 index 000000000..23467aed9 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/MANET.ned @@ -0,0 +1,101 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +package manet; + +import inet.networklayer.autorouting.ipv4.FlatNetworkConfigurator; +import inet.nodes.inet.Router; +import inet.nodes.inet.StandardHost; +import inet.nodes.inet.WirelessHost; +import inet.world.radio.ChannelControl; +import org.mixim.base.connectionManager.ConnectionManager; +import org.mixim.base.modules.BaseWorldUtility; +import inet.nodes.inet.Router; +import inet.networklayer.autorouting.ipv4.IPv4NetworkConfigurator; +import ned.DatarateChannel; + +network MANET +{ + parameters: + double playgroundSizeX @unit(m) = default(1000m); // x size of the area the nodes are in (in meters) + double playgroundSizeY @unit(m) = default(1000m); // y size of the area the nodes are in (in meters) + double playgroundSizeZ @unit(m) = default(1000m); // z size of the area the nodes are in (in meters) + + bool visualize = default(true); + double playgroundLatitude = default(0.0); // geographic position of the playground's north-west corner + double playgroundLongitude = default(0.0); // geographic position of the playground's north-west corner + + int numNodes; + int numRouters = default(0); + + bool ethernet = default(false); + + @display("bgb=469,300,white;bgp=10,50"); + types: + channel C extends DatarateChannel + { + delay = 1us; + datarate = 512Mbps; + } + submodules: + + world: BaseWorldUtility { + parameters: + playgroundSizeX = playgroundSizeX; + playgroundSizeY = playgroundSizeY; + playgroundSizeZ = playgroundSizeZ; + @display("p=37,25"); + } + channel80211: ConnectionManager { + parameters: + @display("p=132,25"); + } + channel802154: ConnectionManager { + parameters: + @display("p=264,25"); + } + channelControl: ChannelControl { + parameters: + @display("p=391,24"); + } + + node[numNodes]: Node { + useEthernet = ethernet; + } + router[numRouters]: Router {} + + switch: Switch {} + + configurator: IPv4NetworkConfigurator { + @display("p=140,50"); + } + + //Visualization + visualizationController: VisualizationController if visualize { + @display("p=90,250"); + } + kmlHttpServer: KmlHttpServer if visualize { + @display("p=320,250;t=Run the simulation in Fast mode\\, then\npoint your browser to localhost:4242\nor open the provided KML file"); + } + connections allowunconnected: + //Connect routers + for i=0..numRouters-1 { + router[i].ethg++ <--> C <--> switch.ethg++ if !ethernet; + } + + for i=0..numNodes-1 { + node[i].ethg <--> C <--> switch.ethg++ if ethernet; + } +} diff --git a/jdeeco-simulation-omnet-native/models/Nic802154_TI_CC2420_Decider.xml b/jdeeco-simulation-omnet-native/models/Nic802154_TI_CC2420_Decider.xml new file mode 100644 index 000000000..eee801864 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/Nic802154_TI_CC2420_Decider.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/jdeeco-simulation-omnet-native/models/Node.ned b/jdeeco-simulation-omnet-native/models/Node.ned new file mode 100644 index 000000000..d7c7d7c1d --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/Node.ned @@ -0,0 +1,168 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +package manet; + +import inet.nodes.inet.WirelessHost; +import org.mixim.modules.power.battery.BatteryStats; +import org.mixim.modules.power.battery.SimpleBattery; +import inet.applications.IPingApp; +import inet.applications.ISCTPApp; +import inet.applications.ITCPApp; +import inet.applications.IUDPApp; +import inet.transport.ISCTP; +import inet.transport.ITCP; +import inet.transport.IUDP; +import inet.util.PcapRecorder; +import inet.networklayer.ipv4.RoutingTable; +import inet.networklayer.common.InterfaceTable; +import inet.mobility.IMobility; +import inet.linklayer.IWirelessNic; +import inet.linklayer.IWiredNic; +import inet.linklayer.IExternalNic; +import inet.base.NotificationBoard; +import inet.nodes.inet.NetworkLayer; +import inet.transport.udp.UDP; + +// This host is an example on how a host with INET network stack +// can be equipped with mobility- and wireless-modules from MiXiM. +// +// It contains an INET network stack and a MiXiM 802.15.4 NIC (TI_CC2420) +// as well as a battery module from MiXiM which is used by the NIC. +// +// This host's NIC is able to operate in a multi-ConnectionManager +// network, i.e. more than one physical network in parallel (non-interfering). +// TODO: factor out battery into INET + +module Node +{ + + parameters: + @display("i=device/pc2"); + @node; + @labels(node,ethernet-node,wireless-node); + + //IP protoctol + bool IPForward = default(false); // disable routing by default + string routingFile = default(""); + bool forwardMulticast = default(false); + bool useEthernet = default(false); + + //NIC + string nic802154Type = default(""); + string nic80211Type = default(""); + + string mobilityType = default(numRadios > 0 ? "StationaryMobility" : ""); + + gates: + input radio80211In @directIn; + input radio802154In @directIn; + inout ethg @labels(EtherFrame-conn); + inout direct[]; + submodules: + + //Application + appl: JDEECoApplication { + parameters: + @display("p=70,30;i=app"); + } + + udp: UDP if nic80211Type != "" || useEthernet { + parameters: + @display("p=329,141"); + } + + // optional mobility module. Required only if wireless cards are present + mobility: like IMobility if mobilityType != "" { + parameters: + @display("p=53,111"); + } + + //Network layer + networkLayer: NetworkLayer if nic80211Type != "" || useEthernet { + parameters: + proxyARP = true; + @display("p=329,287;q=queue"); + } + + routingTable: RoutingTable { + parameters: + @display("p=53,225;is=s"); + IPForward = IPForward; + forwardMulticast = forwardMulticast; + routingFile = routingFile; + } + + //linklayer + interfaceTable: InterfaceTable { + parameters: + @display("p=53,287;is=s"); + } + + //NIC + nic80211: like IWirelessNic if nic80211Type != "" { + parameters: + @display("p=132,406,row,60;q=queue"); + } + nic802154: like IWirelessNic if nic802154Type != "" { + parameters: + @display("p=132,406,row,60;q=queue"); + } + + eth: like IWiredNic if useEthernet { + parameters: + @display("p=368,406,row,60;q=txQueue"); + } + + //Battery + batteryStats: BatteryStats { + @display("p=60,106;i=block/circle"); + } + battery: SimpleBattery { + @display("p=60,176;i=block/control"); + } + notificationBoard: NotificationBoard { + parameters: + @display("p=53,155;is=s"); + } + + connections allowunconnected: + + //# Connect IP branch + if (useEthernet) { + ethg <--> { @display("m=s"); } <--> eth.phys; + eth.upperLayerOut --> networkLayer.ifIn++; + eth.upperLayerIn <-- networkLayer.ifOut++; + } + if (!useEthernet && nic80211Type != "") { + nic80211.upperLayerOut --> networkLayer.ifIn++; + nic80211.upperLayerIn <-- networkLayer.ifOut++; + } + + if (nic80211Type != "" || useEthernet) { + udp.ipOut --> networkLayer.udpIn; + udp.ipIn <-- networkLayer.udpOut; + udp.appOut++ --> appl.lowerLayerIn; + udp.appIn++ <-- appl.lowerLayerOut; + } + + //# Connect MANET branch + + if (nic802154Type != "") { + nic802154.upperLayerOut --> appl.lower802154LayerIn; + nic802154.upperLayerIn <-- appl.lower802154LayerOut; + } +} + diff --git a/jdeeco-simulation-omnet-native/models/Switch.ned b/jdeeco-simulation-omnet-native/models/Switch.ned new file mode 100644 index 000000000..c406421a1 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/Switch.ned @@ -0,0 +1,80 @@ +// +// Copyright (C) 2003 Andras Varga; CTIE, Monash University, Australia +// 2010 Zoltan Bojthe +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program; if not, see . +// + +package manet; + +import inet.base.NotificationBoard; +import inet.linklayer.IMACRelayUnit; +import inet.linklayer.IWiredNic; +import inet.networklayer.common.InterfaceTable; +import inet.status.NodeStatus; +import inet.linklayer.ethernet.EthernetInterface; +import inet.linklayer.ethernet.switch.MACRelayUnitNP; + + +// +// Model of an Ethernet switch. +// +// The duplexChannel attributes of the MACs must be set according to the +// medium connected to the port; if collisions are possible (it's a bus or hub) +// it must be set to false, otherwise it can be set to true. +// By default used half duples CSMA/CD mac +// +// This model does not contain the spanning tree algorithm. +// +module Switch +{ + parameters: + @node(); + @labels(node,ethernet-node); + @display("i=device/switch"); + bool hasStatus = default(false); + gates: + inout ethg[] @labels(EtherFrame-conn); + submodules: + status: NodeStatus if hasStatus { + @display("p=50,50;is=s"); + } + interfaceTable: InterfaceTable { + @display("p=50,100;is=s"); + } + notificationBoard: NotificationBoard { + parameters: + @display("p=50,150;is=s"); + } + relayUnit: MACRelayUnitNP { + parameters: + @display("p=270,50"); + addressTableSize = 10000; + numCPUs = sizeof(ethg); + } + eth[sizeof(ethg)]: CustomEthernetInterface { + parameters: + csmacdSupport = false; + encapType = "EtherEncapDummy"; + mac.promiscuous = true; + mac.txQueueLimit = default(1000000); + @display("p=170,150,row;q=txQueue"); + } + connections: + for i=0..sizeof(ethg)-1 { + eth[i].upperLayerIn <-- relayUnit.ifOut++; + eth[i].upperLayerOut --> relayUnit.ifIn++; + eth[i].phys <--> ethg[i]; + } +} diff --git a/jdeeco-simulation-omnet-native/models/VisualizationController.ned b/jdeeco-simulation-omnet-native/models/VisualizationController.ned new file mode 100644 index 000000000..11dafbdb2 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/VisualizationController.ned @@ -0,0 +1,19 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +// +// This module is responsible for tracking the distance of mobile nodes, +// and visualizing the connectivity graph via KML. +// +package manet; + +simple VisualizationController +{ + @display("i=block/network2"); +} diff --git a/jdeeco-simulation-omnet-native/models/config80211.xml b/jdeeco-simulation-omnet-native/models/config80211.xml new file mode 100644 index 000000000..b460f27cf --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/config80211.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jdeeco-simulation-omnet-native/models/config802154.xml b/jdeeco-simulation-omnet-native/models/config802154.xml new file mode 100644 index 000000000..ad6bd8df5 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/config802154.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/jdeeco-simulation-omnet-native/models/network.cfg b/jdeeco-simulation-omnet-native/models/network.cfg new file mode 100644 index 000000000..bcd58bef6 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/network.cfg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/jdeeco-simulation-omnet-native/models/node80211.route b/jdeeco-simulation-omnet-native/models/node80211.route new file mode 100644 index 000000000..ace9cad21 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/node80211.route @@ -0,0 +1,11 @@ +ifconfig: + +# WLAN to router +name: wlan0 inet_addr: 145.236.0.3 + +ifconfigend. + + +route: +default: 145.236.0.1 0.0.0.0 G 0 wlan0 +routeend. \ No newline at end of file diff --git a/jdeeco-simulation-omnet-native/models/package.ned b/jdeeco-simulation-omnet-native/models/package.ned new file mode 100644 index 000000000..68af13bc3 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/package.ned @@ -0,0 +1 @@ +package manet; diff --git a/jdeeco-simulation-omnet-native/models/router.route b/jdeeco-simulation-omnet-native/models/router.route new file mode 100644 index 000000000..8cb52d9c3 --- /dev/null +++ b/jdeeco-simulation-omnet-native/models/router.route @@ -0,0 +1,18 @@ +ifconfig: + +# NICs of router +name: wlan0 inet_addr: 145.236.0.1 +name: wlan1 inet_addr: 145.236.0.1 +name: wlan2 inet_addr: 145.236.0.1 +name: eth0 inet_addr: 145.236.0.1 + +ifconfigend. + + +route: +default: * 0.0.0.0 H 0 wlan0 +145.236.0.2 * 255.255.255.255 H 0 eth0 +145.236.0.3 * 255.255.255.255 H 0 wlan0 +145.236.0.4 * 255.255.255.255 H 0 wlan1 +145.236.0.5 * 255.255.255.255 H 0 wlan2 +routeend. \ No newline at end of file diff --git a/jdeeco-simulation-omnet-native/omnet-config/configure.user b/jdeeco-simulation-omnet-native/omnet-config/configure.user new file mode 100644 index 000000000..9b0e39a2d --- /dev/null +++ b/jdeeco-simulation-omnet-native/omnet-config/configure.user @@ -0,0 +1,215 @@ +# configure.user +# +# This file contains additional input for 'configure'. It is read (sourced) +# during the configuration process. You are free to edit the settings in here. +# +# The settings in this file are all optional in the sense that they all +# have reasonable default values in the configure script. +# + +# +# Edit here if you want to use a different compiler from the one autodetected +# by configure. +# +#CC=gcc +#CXX=g++ + +# +# Compiler optimization switches. There are two sets of switches, +# and the MODE variable ("debug" or "release") decides which one gets used. +# (Note: For maximum debugging info use switch -ggdb or -gstabs+3 when using gcc and gdb) +# With gcc, do NOT use --omit-frame-pointer (it crashes when coroutines and +# C++ exceptions (throw/catch) are used together)! +# +#CFLAGS_DEBUG='-g -Wall' +#CFLAGS_RELEASE='-O2 -DNDEBUG=1' + +# +# Linker switches used for linking. +# For example use the -m64 switch to build 64 bit binaies on a 32bit operating system +# (only if the 64bit libraries are installed of course). You should add the -m64 flag +# to the CFLAGS_... variables too !!! +# NOTE: that not all 64 bit libraries may be present on your system (i.e. Tcl/Tk and other +# libraries may be missing. Use the NO_TCL=yes if you want to skip the Tcl/Tk based parts) +# +#LDFLAGS="" + +# +# It is possible to have the Tcl files embedded into the compiled OMNeT++ +# libraries and executables. This can be useful if you want to ship +# self-contained standalone executables which do not rely on external +# Tcl scripts. This option is available for Tkenv. +# +EMBED_TCL_CODE=yes + +# +# Set to "yes" to enable simulation executables to load NED files dynamically. +# +WITH_NETBUILDER=yes + +# +# Set to "yes" to enable the parallel distributed simulation feature. +# +WITH_PARSIM=yes + +# +# Set to "yes" to enable SystemC support. (Available only in the commecial version (OMNEST)) +# Please note that SystemC is not supported on MacOS and on the MinGW compiler on Windows. +# +SYSTEMC=no + +# +# Set to no if you want to create static OMNeT++ libraries. Can be overriden +# with "make SHARED_LIBS=no" but then simulation models also need to be built +# with "make SHARED_LIBS=no" +# +SHARED_LIBS=yes + +# +# Compiler and linker options for Tcl/Tk +# +# You can explicitly tell 'configure' which compile switches (TK_CFLAGS) +# and linker switches (TK_LIBS) are needed to build an application with Tcl/Tk. +# Normally these settings are autodetected by 'configure', so you only need to +# edit here if autodetection doesn't work. +# +# With gcc, settings typically look like this: +# +# exaple:TK_CFLAGS="-I/usr/local/include" +# example:TK_LIBS="-L/usr/local/lib -ltk8.4 -ltcl8.4" +# +# /usr/local/include should be replaced with the directory where tcl.h and tk.h +# live. If they are in two different directories, use two -I switches. +# +# /usr/local/lib should be replaced with the directory that contains the Tcl/Tk +# library files (something like libtcl84.so, libtk8.4.a etc; search for libtcl* +# and libtk* to find them.) The -l options contain the library names: the +# library file names, with the leading 'lib' and trailing '.so*' or '.a*' cut +# off. Sometimes you need to explicitly link with the X11 libraries too, in that +# case add -lX11 to TK_LIBS. +# +# With MinGW I use the following: +# Note that we are using the "bin" directory as the LIB dir. +# i.e. directly linking to the DLLs instead of the importlibs in the "lib" directory. +# +#TK_CFLAGS="-I/c/Tools/Tcl-8.4.11/include" +#TK_LIBS="-L/c/Tools/Tcl-8.4.11/bin -ltk84 -ltcl84" +# or: +#TK_CFLAGS="-I$MSYS/include/tcl8.4" +#TK_LIBS="-L$MSYS/bin -ltk84 -ltcl84" + +# +# With Cygwin, you can try: +# examle:TK_CFLAGS= +# examle:TK_LIBS="-ltk84 -ltcl84" +# +# If commented out, the configure script will try to autodetect it +# +# If you don't have Tcl/Tk installed, adding +# NO_TCL=true +# below lets you build just the non-GUI components. + +# +# BLT is a Tcl/Tk extension needed by the Tkenv component of OMNeT++. +# BLT 2.4z is required. BLT_LIBS should contain the -l flag for BLT. +# Default setting is: +# BLT_LIBS="-lBLT24" +# +# +#BLT_LIBS= + +# +# ZLib is a compression library needed by libxml2 and Tkenv's png support. +# +# On MinGW we use the following (dynamically linking against the DLL) +# +#ZLIB_CFLAGS="-I/c/Tools/zlib-1.2.3/include" +#ZLIB_LIBS="-L/c/Tools/zlib-1.2.3/bin -lzlib1" +# or: +#ZLIB_CFLAGS="-I$MSYS/include" +#ZLIB_LIBS="-L$MSYS/lib -lz" + +ZLIB_CFLAGS="-I$MSYS/include" +ZLIB_LIBS="-L$MSYS/lib -static -lz -Wl,-Bdynamic" + +# +# Compiler flags used to compile JNI code. +# -fno-strict-aliasing is needed for gcc when using -O2 otherwise Java +# native calls don't work +# +#JAVA_CFLAGS=-fno-strict-aliasing + +# +# Compiler and linker options for MPI (optional component). +# On LAM/MPI, typing `mpic++ -showme' can give you a hint about MPI_LIBS. +# +# If commented out, the configure script will try to autodetect it +# +#MPI_CFLAGS="-I /usr/include" +#MPI_LIBS="-pthread -llammpio -llammpi++ -llamf77mpi -lmpi -llam -laio -laio -lutil" +#MPI_LIBS="-lmpi++ -lmpi" #SGI + +# +# Compiler and linker options for Expat (optional component) +# +# With MinGW I use the following: +# EXPAT_CFLAGS="-I/d/home/tools/expat-1.95.2/Source/lib" +# EXPAT_LIBS="-L/d/home/tools/expat-1.95.2/libs -lexpat" +# If commented out, the configure script will try to autodetect it +# +#EXPAT_CFLAGS= +#EXPAT_LIBS= + +# +# Compiler and linker options for LIBXML (optional component) +# +# With MinGW I use the following: +# LIBXML_CFLAGS="-I/c/Tools/libxml2-2.6.20.win32/include -I/c/Tools/iconv-1.9.1.win32/include" +# LIBXML_LIBS="-L/c/Tools/libxml2-2.6.20.win32/bin -lxml2 -L/c/Tools/iconv-1.9.1.win32/lib -liconv" +# or: +# LIBXML_CFLAGS="-I$MSYS/include" +# LIBXML_LIBS="-L$MSYS/bin -lxml2 -L$MSYS/bin -liconv" +# If commented out, the configure script will try to autodetect it +# + +LIBXML_CFLAGS="-I$MSYS/include" +LIBXML_LIBS="-L$MSYS/lib -static -lxml2 -L$MSYS/lib -liconv -Wl,-Bdynamic" + +# +# Compiler and linker options for Akaroa (optional component) +# +# With MinGW I use the following: +# AKAROA_CFLAGS="-I/d/home/tools/akaroa-2.7.4/include" +# AKAROA_LIBS="-L/d/home/tools/akaroa-2.7.4/lib -lakaroa" +# If commented out, the configure script will try to autodetect it +# +#AKAROA_CFLAGS= +#AKAROA_LIBS= + +# +# The following OMNETPP_* variables don't need to be touched unless +# you want to relocate parts of the package (e.g. put libraries to +# /usr/lib, include files to /usr/include/omnetpp, and so on). +# +#OMNETPP_SRC_DIR="$OMNETPP_ROOT/src" +#OMNETPP_SAMPLES_DIR="$OMNETPP_ROOT/samples" +#OMNETPP_BIN_DIR="$OMNETPP_ROOT/bin" +#OMNETPP_INCL_DIR="$OMNETPP_ROOT/include" +#OMNETPP_LIB_DIR="$OMNETPP_ROOT/lib" + +# +# Some more OMNeT++ variables. They select the programs opp_makemake-generated +# makefiles will use. (They get default values if commented out.) +# +#MSGC="$OMNETPP_BIN_DIR/opp_msgc" + +# +# +# Override the following setting if you have additional icons somewhere else. +# +# OMNETPP_IMAGE_PATH="./images;./bitmaps;$OMNETPP_ROOT/images" + +# +# On MinGW we use the following +#JDK=/c/Tools/jdk1.6.0 +#SWIG=/c/Tools/swigwin-1.3.31/swig diff --git a/jdeeco-simulation-omnet-native/pom.xml b/jdeeco-simulation-omnet-native/pom.xml new file mode 100644 index 000000000..d2515593f --- /dev/null +++ b/jdeeco-simulation-omnet-native/pom.xml @@ -0,0 +1,155 @@ + + 4.0.0 + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco + 2.0.0 + ../jdeeco-parent/pom.xml + + cz.cuni.mff.d3s.jdeeco.simulation.omnet-native + pom + + UTF-8 + ${java.home}/.. + + + install + + + + org.codehaus.mojo + native-maven-plugin + + + + javah + + + + cz.cuni.mff.d3s.deeco.simulation.omnet.OMNetSimulation + + src + + + + + + + maven-clean-plugin + 2.5 + + + clean-javah + + clean + + clean + + + + src + + cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation.h + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.3.1 + + + exec-make-makefiles + compile + + make + + makefiles + JAVA_HOME=${jdk.home} + + + + exec + + + + exec-make-all + compile + + make + + all + JAVA_HOME=${jdk.home} + + + + exec + + + + exec-make-clean + clean + + make + + cleanall + JAVA_HOME=${jdk.home} + + + + exec + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.9 + + + attach-artifacts + package + + attach-artifact + + + + + out/gcc-debug/src/libjdeeco-omnetpp.so + so + linux + + + + + + + + + + + + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco.core + 2.0.0 + + + cz.cuni.mff.d3s.jdeeco + cz.cuni.mff.d3s.jdeeco.simulation + 2.0.0 + + + diff --git a/jdeeco-simulation-omnet-native/src/.gitignore b/jdeeco-simulation-omnet-native/src/.gitignore new file mode 100644 index 000000000..5fc607b9e --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/.gitignore @@ -0,0 +1 @@ +/Makefile diff --git a/jdeeco-simulation-omnet-native/src/CustomMobility.cc b/jdeeco-simulation-omnet-native/src/CustomMobility.cc new file mode 100644 index 000000000..72b540338 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/CustomMobility.cc @@ -0,0 +1,30 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#include "CustomMobility.h" + +Define_Module(CustomMobility); + +void CustomMobility::handleMessage(cMessage *msg) +{ + ASSERT(false); +} + +void CustomMobility::setCurrentPosition(Coord coordinates) +{ + lastPosition.x = coordinates.x; + lastPosition.y = coordinates.y; + lastPosition.z = coordinates.z; +} diff --git a/jdeeco-simulation-omnet-native/src/CustomMobility.h b/jdeeco-simulation-omnet-native/src/CustomMobility.h new file mode 100644 index 000000000..3461494c9 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/CustomMobility.h @@ -0,0 +1,32 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#ifndef __MANET_CUSTOMMOBILITY_H_ +#define __MANET_CUSTOMMOBILITY_H_ + +#include + +/** + * TODO - Generated class + */ +class CustomMobility : public StationaryMobility +{ + protected: + virtual void handleMessage(cMessage *msg); + public: + virtual void setCurrentPosition(Coord coordinates); +}; + +#endif diff --git a/jdeeco-simulation-omnet-native/src/JDEECoApplication.cc b/jdeeco-simulation-omnet-native/src/JDEECoApplication.cc new file mode 100644 index 000000000..29da75863 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/JDEECoApplication.cc @@ -0,0 +1,190 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#include "JDEECoApplication.h" +#include "MacToNetwControlInfo.h" +#include "NetwToMacControlInfo.h" +#include "IPv4ControlInfo.h" +#include "IPvXAddressResolver.h" +#include "UDPControlInfo.h" +#include "CustomMobility.h" + +Define_Module(JDEECoApplication); + +void JDEECoApplication::initialize(int stage) { + if (stage == 1) { + id = par("id").stringValue(); + + if (simulation.getSystemModule()->par("visualize").boolValue()) { + color = par("color").stringValue(); + modelURL = par("modelURL").str(); + modelScale = par("modelScale").doubleValue(); + showTxRange = par("showTxRange").boolValue(); + txRange = par("txRange").doubleValue(); + + playgroundLat = simulation.getSystemModule()->par("playgroundLatitude"); + playgroundLon = simulation.getSystemModule()->par("playgroundLongitude"); + playgroundHeight = simulation.getSystemModule()->par("playgroundSizeY"); + playgroundWidth = simulation.getSystemModule()->par("playgroundSizeX"); + + if (color.empty()) { + // pick a color with a random hue + char buf[16]; + double red, green, blue; + KmlUtil::hsbToRgb(dblrand(), 1.0, 1.0, red, green, blue); + sprintf(buf, "%2.2x%2.2x%2.2x", int(blue * 255), int(green * 255), + int(red * 255)); + color = buf; + } + + KmlHttpServer::getInstance()->addKmlFragmentProvider(this); + VisualizationController::getInstance()->addMobileNode(this); + } + + lowerLayerIn = findGate("lowerLayerIn"); + lowerLayerOut = findGate("lowerLayerOut"); + + lower802154LayerIn = findGate("lower802154LayerIn"); + lower802154LayerOut = findGate("lower802154LayerOut"); + + //UDP conf + port = par("port"); + socket.setOutputGate(gate("lowerLayerOut")); + socket.bind(port); + socket.setBroadcast(true); + socket.joinLocalMulticastGroups(); + + packet80211ByteLength = par("packet80211ByteLength"); + packet802154ByteLength = par("packet802154ByteLength"); + + JDEECoModule::initialize(); + } +} + +void JDEECoApplication::handleMessage(cMessage *msg) { + double rssi = -1.0; + if (!msg->isSelfMessage()) { + MacToNetwControlInfo* cInfo = dynamic_cast(msg->getControlInfo()); + if (cInfo != NULL) { + rssi = cInfo->getRSSI(); + } + } + onHandleMessage(msg, rssi); + delete (msg); +} + +void JDEECoApplication::sendPacket(JDEECoPacket *packet, + const char *recipient) { + if (opp_strcmp("", recipient) == 0) { + if (gate(lower802154LayerOut)->isConnected()) { + NetwToMacControlInfo::setControlInfo(packet, LAddress::L2BROADCAST); + packet->setByteLength(packet802154ByteLength); + send(packet, lower802154LayerOut); + } + } else { + packet->setByteLength(packet80211ByteLength); + socket.sendTo(packet, IPvXAddressResolver().resolve(recipient).get4(), port); + } +} + +const char * JDEECoApplication::getModuleId() { + return id; +} + +bool JDEECoApplication::isPositionInfoAvailable() { + IMobility *mobility = getMobilityModule(); + return mobility != NULL; +} + +double JDEECoApplication::getPositionX() { + IMobility *mobility = getMobilityModule(); + if (mobility != NULL) { + return mobility->getCurrentPosition().x; + } else + return -1.0; +} + +double JDEECoApplication::getPositionY() { + IMobility *mobility = getMobilityModule(); + if (mobility != NULL) { + return mobility->getCurrentPosition().y; + } else + return -1.0; +} + +double JDEECoApplication::getPositionZ() { + IMobility *mobility = getMobilityModule(); + if (mobility != NULL) { + return mobility->getCurrentPosition().z; + } else + return -1.0; +} + +void JDEECoApplication::setPosition(double valX, double valY, double valZ) { + CustomMobility *mobility = dynamic_cast(getMobilityModule()); + if (mobility != NULL) { + Coord currentPosition = mobility->getCurrentPosition(); + Coord newPosition = Coord::ZERO; + newPosition.x = valX; + newPosition.y = valY; + newPosition.z = valZ; + mobility->setCurrentPosition(newPosition); + } +} + +double JDEECoApplication::getTxRange() { + return 249.0; +} + +IMobility *JDEECoApplication::getMobilityModule() { + IMobility *mobility = check_and_cast( + getParentModule()->getSubmodule("mobility")); + return mobility; +} + +std::string JDEECoApplication::getKmlFragment() { + double longitude = x2lon(getPositionX()); + double latitude = y2lat(getPositionY()); + char buf[16]; + sprintf(buf, "%d", getIndex()); + std::string fragment; + fragment += KmlUtil::folderHeader((std::string("folder_") + buf).c_str(), + getFullName()); + + fragment += KmlUtil::placemark((std::string("placemark_") + buf).c_str(), + longitude, latitude, 2 * modelScale, getModuleId(), NULL); + if (showTxRange) + fragment += KmlUtil::disk((std::string("disk_") + buf).c_str(), + longitude, latitude, txRange, "transmission range", NULL, + (std::string("40") + color).c_str()); + if (!modelURL.empty()) { + fragment += KmlUtil::model((std::string("model_") + buf).c_str(), + longitude, latitude, 360, modelScale, modelURL.c_str(), + "3D model", NULL); + } + + fragment += "\n"; + return fragment; +} + +// utility function: converts playground-relative y coordinate (meters) to latitude +double JDEECoApplication::y2lat(double y) { + return KmlUtil::y2lat(playgroundLat, y); +} + +// utility function: converts playground-relative x coordinate (meters) to longitude +double JDEECoApplication::x2lon(double x) { + return KmlUtil::x2lon(playgroundLat, playgroundLon, x); +} diff --git a/jdeeco-simulation-omnet-native/src/JDEECoApplication.h b/jdeeco-simulation-omnet-native/src/JDEECoApplication.h new file mode 100644 index 000000000..0f5625015 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/JDEECoApplication.h @@ -0,0 +1,83 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#ifndef __MANET_JDEECOAPPLICATION_H_ +#define __MANET_JDEECOAPPLICATION_H_ + +#include +#include "BaseModule.h" +#include "JDEECoModule.h" +#include "IMobility.h" + +#include "KmlHttpServer.h" +#include "KmlUtil.h" +#include "VisualizationController.h" +#include "UDPSocket.h" + +/** + * TODO - Generated class + */ +class JDEECoApplication: public cSimpleModule, + public JDEECoModule, + public IMobileApplication, + public IKmlFragmentProvider { + const char * id; + double playgroundLat, playgroundLon; // NW corner of playground, in degrees + double playgroundHeight, playgroundWidth; + std::string color; + std::string modelURL; + double modelScale; + bool showTxRange; + double txRange; + + int lowerLayerIn; + int lowerLayerOut; + + int lower802154LayerIn; + int lower802154LayerOut; + + IMobility *getMobilityModule(); + double y2lat(double y); + double x2lon(double x); + + UDPSocket socket; + int port; + + int packet80211ByteLength; + int packet802154ByteLength; + +protected: + virtual void initialize(int stage); + virtual int numInitStages() const { return 2; } + virtual void handleMessage(cMessage *msg); +public: + JDEECoApplication() {} + virtual const char *getModuleId(); + virtual void sendPacket(JDEECoPacket *packet, const char *recipient); + + //Position + virtual bool isPositionInfoAvailable(); + virtual double getPositionX(); + virtual double getPositionY(); + virtual double getPositionZ(); + + virtual void setPosition(double valX, double valY, double valZ); + + virtual double getTxRange(); + + virtual std::string getKmlFragment(); +}; + +#endif diff --git a/jdeeco-simulation-omnet-native/src/JDEECoModule.h b/jdeeco-simulation-omnet-native/src/JDEECoModule.h new file mode 100644 index 000000000..1021d14b9 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/JDEECoModule.h @@ -0,0 +1,56 @@ +/* + * jDEECoModule.h + * + * Created on: 24 Dec 2013 + * Author: Michal Kit + */ + +#ifndef JDEECOMODULE_H_ +#define JDEECOMODULE_H_ + +#include "config.h" +#include "csimplemodule.h" +#include "JDEECoPacket_m.h" + +#define JDEECO_TIMER_MESSAGE "@jDEECoTimerMessage@" +#define JDEECO_DATA_MESSAGE "@jDEECoPacketMessage@" + +class DLLEXPORT_OR_IMPORT JDEECoModule { + + double currentCallAtTime; + void *currentCallAtMessage; + +public: + JDEECoModule() {currentCallAtTime = -1.0; currentCallAtMessage = NULL; initialized = false; } + virtual ~JDEECoModule() {} + + void callAt(double absoluteTime); + + //Needs to be implemented by the module + virtual const char * getModuleId() {return NULL;}; + //Needs to be implemented by the module + virtual void sendPacket(JDEECoPacket *packet, const char *recipient) {}; + //Needs to be implemented by the module + virtual void scheduleAt(double absoluteTime, cMessage *msg) {}; + //Needs to be implemented by the module + virtual bool isPositionInfoAvailable() {return false;}; + //Needs to be implemented by the module + virtual double getPositionX() {return 0;}; + //Needs to be implemented by the module + virtual double getPositionY() {return 0;}; + //Needs to be implemented by the module + virtual double getPositionZ() {return 0;}; + //Needs to be implemented by the module + virtual void setPosition(double valX, double valY, double valZ) {}; + +protected: + bool initialized; + + //Needs to be called at the module initialisation + void initialize(); + //Needs to be called from the handleMessage method + void onHandleMessage(cMessage *msg, double rssi); + +}; + +#endif /* JDEECOMODULE_H_ */ diff --git a/jdeeco-simulation-omnet-native/src/JDEECoPacket.msg b/jdeeco-simulation-omnet-native/src/JDEECoPacket.msg new file mode 100644 index 000000000..a1054bfc4 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/JDEECoPacket.msg @@ -0,0 +1,17 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// +packet JDEECoPacket { + unsigned char data []; +} diff --git a/jdeeco-simulation-omnet-native/src/KmlHttpServer.cc b/jdeeco-simulation-omnet-native/src/KmlHttpServer.cc new file mode 100644 index 000000000..6f3573762 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/KmlHttpServer.cc @@ -0,0 +1,225 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + + +#include "SocketDataProvider.h" +#include "KmlHttpServer.h" + + +Define_Module(KmlHttpServer); + +KmlHttpServer *KmlHttpServer::instance = NULL; + +KmlHttpServer::KmlHttpServer() +{ + rtEvent = NULL; + if (instance) + error("There can be only one KmlHttpServer instance in the network"); + instance = this; +} + +KmlHttpServer::~KmlHttpServer() +{ + cancelAndDelete(rtEvent); + instance = NULL; +} + +void KmlHttpServer::initialize() +{ + rtEvent = new cMessage("rtEvent"); + socketDataProvider = check_and_cast(simulation.getScheduler()); + socketDataProvider->setInterfaceModule(this, rtEvent, recvBuffer, 4000, &numRecvBytes); +} + +KmlHttpServer *KmlHttpServer::getInstance() +{ + if (!instance) + throw cRuntimeError("KmlHttpServer::getInstance(): there is no KmlHttpServer module in the network"); + return instance; +} + +int KmlHttpServer::findKmlFragmentProvider(IKmlFragmentProvider* p) +{ + for (int i=0; i<(int)providerList.size(); i++) + if (providerList[i] == p) + return i; + return -1; +} + +void KmlHttpServer::addKmlFragmentProvider(IKmlFragmentProvider* p) +{ + if (findKmlFragmentProvider(p) == -1) + providerList.push_back(p); +} + +void KmlHttpServer::removeKmlFragmentProvider(IKmlFragmentProvider* p) +{ + int k = findKmlFragmentProvider(p); + if (k != -1) + providerList.erase(providerList.begin()+k); +} + +void KmlHttpServer::handleMessage(cMessage *msg) +{ + if (msg != rtEvent) + error("This module does not handle messages"); // only those from the SocketRTScheduler + + handleSocketEvent(); +} + +void KmlHttpServer::handleSocketEvent() +{ + // try to find a double line feed in the input -- that's the end of the HTTP header. + char *endHeader = NULL; + for (char *s=recvBuffer; s<=recvBuffer+numRecvBytes-4; s++) + if (*s=='\r' && *(s+1)=='\n' && *(s+2)=='\r' && *(s+3)=='\n') + {endHeader = s+4; break;} + + // we don't have a complete header yet -- keep on waiting + if (!endHeader) + return; + std::string header = std::string(recvBuffer, endHeader-recvBuffer); + //EV << header; + + // remove HTTP header from buffer + if (endHeader == recvBuffer+numRecvBytes) + numRecvBytes = 0; + else { + int bytesLeft = recvBuffer+numRecvBytes-endHeader; + memmove(endHeader, recvBuffer, bytesLeft); + numRecvBytes = bytesLeft; + } + + // process HTTP request + std::string reply = processHttpRequest(header.c_str()); + + // send back reply + socketDataProvider->sendBytes(reply.c_str(), reply.size()); + socketDataProvider->close(); +} + +std::string KmlHttpServer::processHttpRequest(const char *httpReqHeader) +{ + // parse header. first line should be: GET uri HTTP/1.1 + std::string header(httpReqHeader); + std::string::size_type pos = header.find("\r\n"); + if (pos==std::string::npos) + { + EV << "Bad HTTP request\n"; + return std::string("HTTP/1.0 400 Bad Request\r\n"); + } + + std::string cmd(header,0,pos); + EV << "Received: " << cmd << "\n"; + + // we only accept GET + if (cmd.length()<4 || cmd.compare(0,4,"GET ")) + { + EV << "Wrong HTTP verb, only GET is supported\n"; + return std::string("HTTP/1.0 501 Not Implemented\r\n"); + } + + // parse URI and get corresponding content + pos = cmd.find(" ",4); + std::string uri(cmd,4,pos-4); + + // create and return reply + std::string reply = getReplyFor(uri.c_str()); + return reply; +} + +const char *INDEX_HTML = + "\n" + "\n" + " OMNeT++ Google Earth Demo\n" + " \n" // ID registered for omnetpp.org + " \n" + "\n" + "\n" + "\n" + "
\n" + "\n" + "\n"; + +std::string KmlHttpServer::getReplyFor(const char *uri) +{ + if (strcmp(uri, "/")==0 || strcmp(uri, "/index.html")==0) + { + return addHttpHeader(INDEX_HTML, "text/html"); + } + if (strcmp(uri, "/snapshot.kml")==0) + { + std::stringstream out; + out << "\n"; + out << "\n"; + out << "\n"; + for (int i=0; i<(int)providerList.size(); i++) + out << providerList[i]->getKmlFragment(); + out << "\n"; + out << "\n"; + + return addHttpHeader(out.str().c_str(), "application/vnd.google-earth.kml+xml"); + } + return "HTTP/1.0 404 Not Found\r\n\r\n"; +} + +std::string KmlHttpServer::addHttpHeader(const char *content, const char *mimetype) +{ + // assemble reply + std::stringstream out; + out << "HTTP/1.0 200 OK\r\n"; + out << "Content-Type: " << mimetype << "\r\n"; + //out << "Content-Length: " << strlen(content) << "\r\n"; + out << "\r\n"; + out << content; + return out.str(); +} + diff --git a/jdeeco-simulation-omnet-native/src/KmlHttpServer.h b/jdeeco-simulation-omnet-native/src/KmlHttpServer.h new file mode 100644 index 000000000..a3c283265 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/KmlHttpServer.h @@ -0,0 +1,68 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#ifndef __KMLHTTPSERVER_H__ +#define __KMLHTTPSERVER_H__ + +#include + +class cSocketDataProvider; + +/** + * Interface for objects that want to provide KML markup + * fragments into the document returned by KmlHttpServer. + */ +class IKmlFragmentProvider +{ + public: + virtual std::string getKmlFragment() = 0; +}; + + +/** + * Answers HTTP GET requests that arrive to the built-in web server + * of the simulation, and returns KML or HTML documents. + * + * KML is assembled from markup fragments provided by the + * registered IKmlFragmentProviders. + */ +class KmlHttpServer : public cSimpleModule +{ + protected: + static KmlHttpServer *instance; + + cMessage *rtEvent; + cSocketDataProvider *socketDataProvider; + char recvBuffer[4000]; + int numRecvBytes; + + std::vector providerList; + + protected: + int findKmlFragmentProvider(IKmlFragmentProvider* p); + + public: + KmlHttpServer(); + virtual ~KmlHttpServer(); + + static KmlHttpServer *getInstance(); + virtual void addKmlFragmentProvider(IKmlFragmentProvider* p); + virtual void removeKmlFragmentProvider(IKmlFragmentProvider* p); + + protected: + virtual void initialize(); + virtual void handleMessage(cMessage *msg); + virtual void handleSocketEvent(); + virtual std::string processHttpRequest(const char *request); + virtual std::string getReplyFor(const char *uri); + virtual std::string addHttpHeader(const char *content, const char *mimetype); +}; + +#endif + diff --git a/jdeeco-simulation-omnet-native/src/KmlUtil.cc b/jdeeco-simulation-omnet-native/src/KmlUtil.cc new file mode 100644 index 000000000..01a2a9a7f --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/KmlUtil.cc @@ -0,0 +1,335 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#include "KmlUtil.h" + + +std::string KmlUtil::folderHeader(const char *id, const char *name, const char *description) +{ + std::stringstream out; + out.precision(8); + out << "\n"; + + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + return out.str(); +} + +std::string KmlUtil::placemark(const char *id, float lon, float lat,float alt, const char *name, const char *description) +{ + std::stringstream out; + out.precision(8); + out << "\n"; + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + out << " \n"; + out << " \n"; + out << " relativeToGround\n"; + out << " " << lon << "," << lat << "," << alt << "\n"; + out << " \n"; + out << "\n"; + return out.str(); +} + +std::string KmlUtil::lines(const char *id, const std::vector& pts, const char *name, const char *description, const char *color) +{ + std::stringstream out; + out.precision(8); + out << "\n"; + if (color) { + out << " \n"; + } + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + out << " \n"; + for (int i=0; i<(int)pts.size()-1; i+=2) + { + out << " \n"; + out << " false\n"; + out << " true\n"; + out << " "; + out << pts[i].lon << "," << pts[i].lat << " " << pts[i+1].lon << "," << pts[i+1].lat; + out << "\n"; + out << " \n"; + } + out << " \n"; + out << "\n"; + return out.str(); +} + +std::string KmlUtil::lineString(const char *id, const std::vector& pts, const char *name, const char *description, const char *color) +{ + std::stringstream out; + out.precision(8); + out << "\n"; + if (color) { + out << " \n"; + } + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + out << " \n"; + out << " false\n"; + out << " true\n"; + out << " "; + for (int i=0; i<(int)pts.size(); i++) + out << pts[i].lon << "," << pts[i].lat << " "; + out << "\n"; + out << " \n"; + out << "\n"; + return out.str(); +} + +std::string KmlUtil::disk(const char *id, float lon, float lat, float r, const char *name, const char *description, const char *color) +{ + static const int N = 40; + static float x[N], y[N]; + static bool initialized = false; + if (!initialized) { + for (int i=0; i\n"; + if (color) { + out << " \n"; + } + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + out << " \n"; + out << " false\n"; + out << " \n"; + out << " \n"; + out << " \n"; + for (int i=0; i\n"; + out << " \n"; + out << " \n"; + out << " \n"; + out << "\n"; + return out.str(); +} + +std::string KmlUtil::model(const char *id, float lon, float lat, float heading, float scale, const char *link, const char *name, const char *description) +{ + std::stringstream out; + out.precision(8); + out << "\n"; + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + + out << " \n"; + out << " relativeToGround\n"; + out << " \n"; + out << " " << lon << "\n"; + out << " " << lat << "\n"; + //out << " 0\n"; + out << " \n"; + out << " \n"; + out << " " << heading << "\n"; + //out << " 0\n"; + //out << " 0\n"; + out << " \n"; + out << " \n"; + out << " " << scale << "\n"; + out << " " << scale << "\n"; + out << " " << scale << "\n"; + out << " \n"; + out << " \n"; + out << " " << link << "\n"; + out << " \n"; + out << " \n"; + + out << "\n"; + return out.str(); +} + +std::string KmlUtil::track(const char *id, const std::vector& pts, float timeStep, float modelScale, const char *modelLink, const char *name, const char *description, const char *color) +{ + std::stringstream out; + out.precision(8); + + out << "\n"; + if (color) { + out << " \n"; + } + if (name) + out << " " << name << "\n"; + if (description) + out << " " << description << "\n"; + + out << " \n"; + double t = SIMTIME_DBL(simTime() - (pts.size()-1)*timeStep); + for (int i=0; i<(int)pts.size(); i++, t+= timeStep) { + int x = (int)t; //NOTE: timeStep < 1 will result in multiple timestamps with the same value!!! + int ss = x % 60; x-= ss; x/=60; + int mm = x % 60; x-= mm; x/=60; + int hh = x; + char when[100]; + sprintf(when, "2010-05-28T%2.2d:%2.2d:%2.2dZ", hh, mm, ss); //TODO better conversion! (localtime()+sprintf()?) + out << " " << when << "\n"; + } + for (int i=0; i<(int)pts.size(); i++) + out << " " << pts[i].lon << " " << pts[i].lat << "\n"; + + if (modelLink) { + out << " \n"; + out << " \n"; + out << " " << 0 << "\n"; //TODO compute from first two points + out << " \n"; + out << " \n"; + out << " " << modelScale << "\n"; + out << " " << modelScale << "\n"; + out << " " << modelScale << "\n"; + out << " \n"; + out << " \n"; + out << " " << modelLink << "\n"; + out << " \n"; + out << " \n"; + } + out << " \n"; + + out << "\n"; + + return out.str(); +} + + +void KmlUtil::hsbToRgb(double hue, double saturation, double brightness, + double& red, double& green, double &blue) +{ + if (brightness == 0.0) + { // safety short circuit again + red = 0.0; + green = 0.0; + blue = 0.0; + return; + } + + if (saturation == 0.0) + { // grey + red = brightness; + green = brightness; + blue = brightness; + return; + } + + float domainOffset; // hue mod 1/6 + if (hue < 1.0/6) + { // red domain; green ascends + domainOffset = hue; + red = brightness; + blue = brightness * (1.0 - saturation); + green = blue + (brightness - blue) * domainOffset * 6; + } + else if (hue < 2.0/6) + { // yellow domain; red descends + domainOffset = hue - 1.0/6; + green = brightness; + blue = brightness * (1.0 - saturation); + red = green - (brightness - blue) * domainOffset * 6; + } + else if (hue < 3.0/6) + { // green domain; blue ascends + domainOffset = hue - 2.0/6; + green = brightness; + red = brightness * (1.0 - saturation); + blue = red + (brightness - red) * domainOffset * 6; + } + else if (hue < 4.0/6) + { // cyan domain; green descends + domainOffset = hue - 3.0/6; + blue = brightness; + red = brightness * (1.0 - saturation); + green = blue - (brightness - red) * domainOffset * 6; + } + else if (hue < 5.0/6) + { // blue domain; red ascends + domainOffset = hue - 4.0/6; + blue = brightness; + green = brightness * (1.0 - saturation); + red = green + (brightness - green) * domainOffset * 6; + } + else + { // magenta domain; blue descends + domainOffset = hue - 5.0/6; + red = brightness; + green = brightness * (1.0 - saturation); + blue = red - (brightness - green) * domainOffset * 6; + } +} + diff --git a/jdeeco-simulation-omnet-native/src/KmlUtil.h b/jdeeco-simulation-omnet-native/src/KmlUtil.h new file mode 100644 index 000000000..1cf9332cc --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/KmlUtil.h @@ -0,0 +1,66 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#ifndef __KMLUTIL_H__ +#define __KMLUTIL_H__ + +#include + +#ifndef M_PI +#define M_PI 3.14159265 // needed on Windows +#endif + +/** + * A collection of utility functions to generate KML markup for this demo + */ +class KmlUtil +{ + public: + struct Pt2D {float lon, lat; Pt2D() {lon=lat=0;} Pt2D(float lo, float la) {lon=lo; lat=la;}}; + struct Pt3D {float lon, lat, alt; Pt3D() {lon=lat=alt=0;} Pt3D(float lo, float la, float al) {lon=lo; lat=la; alt=al;}}; + + /** Generates the start of a KML folder; just add content and a close tag. */ + static std::string folderHeader(const char *id=NULL, const char *name=NULL, const char *description=NULL); + + /** Generates a floating placemark, displayed as a white arrow pointing downwards, with a label */ + static std::string placemark(const char *id, float lon, float lat, float alt, const char *name=NULL, const char *description=NULL); + + /** Generates placemark containing a line of connected line segments */ + static std::string lineString(const char *id, const std::vector& pts, const char *name=NULL, const char *description=NULL, const char *color=NULL); + + /** Generates placemark containing several disjoint line segments */ + static std::string lines(const char *id, const std::vector& pts, const char *name=NULL, const char *description=NULL, const char *color=NULL); + + /** Generates placemark containing a disc with the given radius (meters), approximated with a polygon */ + static std::string disk(const char *id, float lon, float lat, float r, const char *name=NULL, const char *description=NULL, const char *color=NULL); + + /** Generates placemark containing a 3-D model */ + static std::string model(const char *id, float lon, float lat, float heading, float scale, const char *link, const char *name=NULL, const char *description=NULL); + + /** Generates placemark containing a track (gx:Track KML element) */ + static std::string track(const char *id, const std::vector& pts, float timeStep, float modelScale, const char *modelLink, const char *name=NULL, const char *description=NULL, const char *color=NULL); + + /** + * Returns the latitude yoff meters to the north (or south if yoff<0) from latitude lat + */ + static double y2lat(double lat, double yoff) { return lat - yoff / 111111; } + + /** + * Returns the longitude of the place xoff meters to the east (or west if xoff<0) of the place (lon, lat) + */ + static double x2lon(double lat, double lon, double xoff) { return lon + xoff / 111111 / cos(fabs(lat/180*M_PI)); } + + /** + * Converts a color given in HSB to RGB. + */ + static void hsbToRgb(double hue, double saturation, double brightness, double& red, double& green, double &blue); +}; + +#endif + diff --git a/jdeeco-simulation-omnet-native/src/SocketDataProvider.h b/jdeeco-simulation-omnet-native/src/SocketDataProvider.h new file mode 100644 index 000000000..62ed1dfb9 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/SocketDataProvider.h @@ -0,0 +1,42 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#ifndef SOCKETDATAPROVIDER_H_ +#define SOCKETDATAPROVIDER_H_ + +#include + +class cSocketDataProvider { +public: + /** + * To be called from the module which wishes to receive data from the + * socket. The method must be called from the module's initialize() + * function. + */ + virtual void setInterfaceModule(cModule *module, cMessage *notificationMsg, + char *recvBuffer, int recvBufferSize, int *numBytesPtr) = 0; + + /** + * Send on the currently open connection + */ + virtual void sendBytes(const char *buf, size_t numBytes) = 0; + + /** + * Close the currently open connection + */ + virtual void close() = 0; +}; + +#endif /* SOCKETDATAPROVIDER_H_ */ diff --git a/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.cc b/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.cc new file mode 100644 index 000000000..79f893054 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.cc @@ -0,0 +1,252 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + + +#include "SocketRealTimeScheduler.h" + +#ifndef _WIN32 +#define closesocket(x) ::close(x) +#endif + + +Register_Class(cSocketRealTimeScheduler); + +Register_GlobalConfigOption(CFGID_SOCKETREALTIMESCHEDULER_PORT, "socketrealtimescheduler-port", CFG_INT, "4242", "When cSocketRealTimeScheduler is selected as scheduler class: the port number cSocketRTScheduler listens on."); + +inline std::ostream& operator<<(std::ostream& out, const timeval& tv) +{ + return out << (unsigned long)tv.tv_sec << "s" << tv.tv_usec << "us"; +} + +//--- + +cSocketRealTimeScheduler::cSocketRealTimeScheduler() : cScheduler() +{ + listenerSocket = INVALID_SOCKET; + connSocket = INVALID_SOCKET; +} + +cSocketRealTimeScheduler::~cSocketRealTimeScheduler() +{ +} + +void cSocketRealTimeScheduler::startRun() +{ + if (initsocketlibonce()!=0) + throw cRuntimeError("cSocketRTScheduler: Cannot initialize socket library"); + + gettimeofday(&baseTime, NULL); + + module = NULL; + notificationMsg = NULL; + recvBuffer = NULL; + recvBufferSize = 0; + numBytesPtr = NULL; + + port = ev.getConfig()->getAsInt(CFGID_SOCKETREALTIMESCHEDULER_PORT); + setupListener(); +} + +void cSocketRealTimeScheduler::setupListener() +{ + listenerSocket = socket(AF_INET, SOCK_STREAM, 0); + if (listenerSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketRTScheduler: cannot create socket"); + + sockaddr_in sinInterface; + sinInterface.sin_family = AF_INET; + sinInterface.sin_addr.s_addr = INADDR_ANY; + sinInterface.sin_port = htons(port); + if (bind(listenerSocket, (sockaddr*)&sinInterface, sizeof(sockaddr_in))==SOCKET_ERROR) + throw cRuntimeError("cSocketRTScheduler: socket bind() failed"); + + listen(listenerSocket, SOMAXCONN); +} + +void cSocketRealTimeScheduler::endRun() +{ +} + +void cSocketRealTimeScheduler::executionResumed() +{ + gettimeofday(&baseTime, NULL); + baseTime = timeval_substract(baseTime, SIMTIME_DBL(simTime())); +} + +void cSocketRealTimeScheduler::setInterfaceModule(cModule *mod, cMessage *notifMsg, char *buf, int bufSize, int *nBytesPtr) +{ + if (module) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule() already called"); + if (!mod || !notifMsg || !buf || !bufSize || !nBytesPtr) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule(): arguments must be non-NULL"); + + module = mod; + notificationMsg = notifMsg; + recvBuffer = buf; + recvBufferSize = bufSize; + numBytesPtr = nBytesPtr; + *numBytesPtr = 0; +} + +bool cSocketRealTimeScheduler::receiveWithTimeout(long usec) +{ + // prepare sets for select() + fd_set readFDs, writeFDs, exceptFDs; + FD_ZERO(&readFDs); + FD_ZERO(&writeFDs); + FD_ZERO(&exceptFDs); + + // if we're connected, watch connSocket, otherwise accept new connections + if (connSocket!=INVALID_SOCKET) + FD_SET(connSocket, &readFDs); + else + FD_SET(listenerSocket, &readFDs); + + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = usec; + + if (select(FD_SETSIZE, &readFDs, &writeFDs, &exceptFDs, &timeout) > 0) + { + // Something happened on one of the sockets -- handle them + if (connSocket!=INVALID_SOCKET && FD_ISSET(connSocket, &readFDs)) + { + // receive from connSocket + char *bufPtr = recvBuffer + (*numBytesPtr); + int bufLeft = recvBufferSize - (*numBytesPtr); + if (bufLeft<=0) + throw cRuntimeError("cSocketRTScheduler: interface module's recvBuffer is full"); + int nBytes = recv(connSocket, bufPtr, bufLeft, 0); + if (nBytes==SOCKET_ERROR) + { + EV << "cSocketRTScheduler: socket error " << sock_errno() << "\n"; + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } + else if (nBytes == 0) + { + EV << "cSocketRTScheduler: socket closed by the client\n"; + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } + else + { + // schedule notificationMsg for the interface module + EV << "cSocketRTScheduler: received " << nBytes << " bytes\n"; + (*numBytesPtr) += nBytes; + + timeval curTime; + gettimeofday(&curTime, NULL); + curTime = timeval_substract(curTime, baseTime); + simtime_t t = curTime.tv_sec + curTime.tv_usec*1e-6; + // TBD assert that it's somehow not smaller than previous event's time + notificationMsg->setArrival(module,-1,t); + simulation.msgQueue.insert(notificationMsg); + return true; + } + } + else if (FD_ISSET(listenerSocket, &readFDs)) + { + // accept connection, and store FD in connSocket + sockaddr_in sinRemote; + int addrSize = sizeof(sinRemote); + connSocket = accept(listenerSocket, (sockaddr*)&sinRemote, (socklen_t*)&addrSize); + if (connSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketRTScheduler: accept() failed"); + EV << "cSocketRTScheduler: connected!\n"; + } + } + return false; +} + +int cSocketRealTimeScheduler::receiveUntil(const timeval& targetTime) +{ + // if there's more than 200ms to wait, wait in 100ms chunks + // in order to keep UI responsiveness by invoking ev.idle() + timeval curTime; + gettimeofday(&curTime, NULL); + while (targetTime.tv_sec-curTime.tv_sec >=2 || + timeval_diff_usec(targetTime, curTime) >= 200000) + { + if (receiveWithTimeout(100000)) // 100ms + return 1; + if (ev.idle()) + return -1; + gettimeofday(&curTime, NULL); + } + + // difference is now at most 100ms, do it at once + long usec = timeval_diff_usec(targetTime, curTime); + if (usec>0) + if (receiveWithTimeout(usec)) + return 1; + return 0; +} + +cMessage *cSocketRealTimeScheduler::getNextEvent() +{ + // assert that we've been configured + if (!module) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule() not called: it must be called from a module's initialize() function"); + + // calculate target time + timeval targetTime; + cMessage *msg = sim->msgQueue.peekFirst(); + if (!msg) + { + // if there are no events, wait until something comes from outside + // TBD: obey simtimelimit, cpu-time-limit + targetTime.tv_sec = LONG_MAX; + targetTime.tv_usec = 0; + } + else + { + // use time of next event + simtime_t eventSimtime = msg->getArrivalTime(); + targetTime = timeval_add(baseTime, SIMTIME_DBL(eventSimtime)); + } + + // if needed, wait until that time arrives + timeval curTime; + gettimeofday(&curTime, NULL); + if (timeval_greater(targetTime, curTime)) + { + int status = receiveUntil(targetTime); + if (status == -1) + return NULL; // interrupted by user + if (status == 1) + msg = sim->msgQueue.peekFirst(); // received something + } + else + { + // we're behind -- customized versions of this class may + // alert if we're too much behind, whatever that means + } + + // ok, return the message + return msg; +} + +void cSocketRealTimeScheduler::sendBytes(const char *buf, size_t numBytes) +{ + if (connSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketRTScheduler: sendBytes(): no connection"); + + send(connSocket, buf, numBytes, 0); + // TBD check for errors +} + +void cSocketRealTimeScheduler::close() +{ + if (connSocket!=INVALID_SOCKET) + { + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } +} diff --git a/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.h b/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.h new file mode 100644 index 000000000..67103cbe6 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/SocketRealTimeScheduler.h @@ -0,0 +1,121 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#ifndef __CSOCKETRTSCHEDULER_H__ +#define __CSOCKETRTSCHEDULER_H__ + +#include +#include + +#include "SocketDataProvider.h" + + + + +/** + * Real-time scheduler with socket-based external communication. + * + * \code + * class MyInterfaceModule : public cSimpleModule + * { + * cSocketRTScheduler *rtScheduler; + * cMessage *extEvent; + * char buf[4000]; + * int numBytes; + * ... + * \endcode + * + * \code + * void MyInterfaceModule::initialize() + * { + * extEvent = new cMessage("extEvent"); + * rtScheduler = check_and_cast(simulation.getScheduler()); + * rtScheduler->setInterfaceModule(this, extEvent, buf, 4000, numBytes); + * } + * \endcode + * + * THIS CLASS IS JUST AN EXAMPLE -- IF YOU WANT TO DO HARDWARE-IN-THE-LOOP + * SIMULATION, YOU WILL NEED TO WRITE YOUR OWN SCHEDULER WHICH FITS YOUR NEEDS. + * For example, you'll probably want a different external interface than + * a single TCP socket: maybe UDP socket, maybe raw socket to grab full Ethernet + * frames, maybe pipe, maybe USB or other interface, etc. + */ +class cSocketRealTimeScheduler : public cScheduler, public cSocketDataProvider +{ + protected: + // config + int port; + + cModule *module; + cMessage *notificationMsg; + char *recvBuffer; + int recvBufferSize; + int *numBytesPtr; + + // state + timeval baseTime; + SOCKET listenerSocket; + SOCKET connSocket; + + virtual void setupListener(); + virtual bool receiveWithTimeout(long usec); + virtual int receiveUntil(const timeval& targetTime); + + public: + /** + * Constructor. + */ + cSocketRealTimeScheduler(); + + /** + * Destructor. + */ + virtual ~cSocketRealTimeScheduler(); + + /** + * Called at the beginning of a simulation run. + */ + virtual void startRun(); + + /** + * Called at the end of a simulation run. + */ + virtual void endRun(); + + /** + * Recalculates "base time" from current wall clock time. + */ + virtual void executionResumed(); + + /** + * To be called from the module which wishes to receive data from the + * socket. The method must be called from the module's initialize() + * function. + */ + virtual void setInterfaceModule(cModule *module, cMessage *notificationMsg, + char *recvBuffer, int recvBufferSize, int *numBytesPtr); + + /** + * Scheduler function -- it comes from cScheduler interface. + */ + virtual cMessage *getNextEvent(); + + /** + * Send on the currently open connection + */ + virtual void sendBytes(const char *buf, size_t numBytes); + + /** + * Close the currently open connection + */ + virtual void close(); +}; + +#endif + diff --git a/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.cc b/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.cc new file mode 100644 index 000000000..a22f8a4eb --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.cc @@ -0,0 +1,178 @@ +/* + * SocketSequentialScheduler.cc + * + * Created on: 3 Feb 2014 + * Author: Michal + */ + +#include "SocketSequentialScheduler.h" + +#ifndef _WIN32 +#define closesocket(x) ::close(x) +#endif + + +Register_Class(cSocketSequentialScheduler); +Register_GlobalConfigOption(CFGID_SOCKETSEQUENTIALSCHEDULER_PORT, "socketsequentialscheduler-port", CFG_INT, "4242", "When cSocketSequentialScheduler is selected as scheduler class: the port number cSocketSequentialScheduler listens on."); + +inline std::ostream& operator<<(std::ostream& out, const timeval& tv) +{ + return out << (unsigned long)tv.tv_sec << "s" << tv.tv_usec << "us"; +} + +//--- + +cSocketSequentialScheduler::cSocketSequentialScheduler() : cSequentialScheduler() +{ + listenerSocket = INVALID_SOCKET; + connSocket = INVALID_SOCKET; +} + +cSocketSequentialScheduler::~cSocketSequentialScheduler() +{ +} + +void cSocketSequentialScheduler::startRun() +{ + if (initsocketlibonce()!=0) + throw cRuntimeError("cSocketRTScheduler: Cannot initialize socket library"); + + module = NULL; + notificationMsg = NULL; + recvBuffer = NULL; + recvBufferSize = 0; + numBytesPtr = NULL; + + port = ev.getConfig()->getAsInt(CFGID_SOCKETSEQUENTIALSCHEDULER_PORT); + setupListener(); +} + +void cSocketSequentialScheduler::setupListener() +{ + listenerSocket = socket(AF_INET, SOCK_STREAM, 0); + if (listenerSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketRTScheduler: cannot create socket"); + + sockaddr_in sinInterface; + sinInterface.sin_family = AF_INET; + sinInterface.sin_addr.s_addr = INADDR_ANY; + sinInterface.sin_port = htons(port); + if (bind(listenerSocket, (sockaddr*)&sinInterface, sizeof(sockaddr_in))==SOCKET_ERROR) + throw cRuntimeError("cSocketRTScheduler: socket bind() failed"); + + listen(listenerSocket, SOMAXCONN); +} + +void cSocketSequentialScheduler::setInterfaceModule(cModule *mod, cMessage *notifMsg, char *buf, int bufSize, int *nBytesPtr) +{ + if (module) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule() already called"); + if (!mod || !notifMsg || !buf || !bufSize || !nBytesPtr) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule(): arguments must be non-NULL"); + + module = mod; + notificationMsg = notifMsg; + recvBuffer = buf; + recvBufferSize = bufSize; + numBytesPtr = nBytesPtr; + *numBytesPtr = 0; + socketCycleCount = 2000; + currentSocketCycleCount = socketCycleCount; +} + +bool cSocketSequentialScheduler::receiveWithTimeout(long usec) +{ + // prepare sets for select() + fd_set readFDs, writeFDs, exceptFDs; + FD_ZERO(&readFDs); + FD_ZERO(&writeFDs); + FD_ZERO(&exceptFDs); + + // if we're connected, watch connSocket, otherwise accept new connections + if (connSocket!=INVALID_SOCKET) + FD_SET(connSocket, &readFDs); + else + FD_SET(listenerSocket, &readFDs); + + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = usec; + + if (select(FD_SETSIZE, &readFDs, &writeFDs, &exceptFDs, &timeout) > 0) + { + // Something happened on one of the sockets -- handle them + if (connSocket!=INVALID_SOCKET && FD_ISSET(connSocket, &readFDs)) + { + // receive from connSocket + char *bufPtr = recvBuffer + (*numBytesPtr); + int bufLeft = recvBufferSize - (*numBytesPtr); + if (bufLeft<=0) + throw cRuntimeError("cSocketSequentialScheduler: interface module's recvBuffer is full"); + int nBytes = recv(connSocket, bufPtr, bufLeft, 0); + if (nBytes==SOCKET_ERROR) + { + EV << "cSocketSequentialScheduler: socket error " << sock_errno() << "\n"; + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } + else if (nBytes == 0) + { + EV << "cSocketSequentialScheduler: socket closed by the client\n"; + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } + else + { + // schedule notificationMsg for the interface module + EV << "cSocketSequentialScheduler: received " << nBytes << " bytes\n"; + (*numBytesPtr) += nBytes; + notificationMsg->setArrival(module,-1,simulation.msgQueue.peekFirst()->getArrivalTime()); + simulation.msgQueue.insert(notificationMsg); + return true; + } + } + else if (FD_ISSET(listenerSocket, &readFDs)) + { + // accept connection, and store FD in connSocket + sockaddr_in sinRemote; + int addrSize = sizeof(sinRemote); + connSocket = accept(listenerSocket, (sockaddr*)&sinRemote, (socklen_t*)&addrSize); + if (connSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketSequentialScheduler: accept() failed"); + EV << "cSocketSequentialScheduler: connected!\n"; + } + } + return false; +} + +cMessage *cSocketSequentialScheduler::getNextEvent() +{ + if (!module) + throw cRuntimeError("cSocketRTScheduler: setInterfaceModule() not called: it must be called from a module's initialize() function"); + + if (currentSocketCycleCount == 0) { + receiveWithTimeout(50); + currentSocketCycleCount = socketCycleCount; + } else + currentSocketCycleCount--; + return cSequentialScheduler::getNextEvent(); +} + +void cSocketSequentialScheduler::sendBytes(const char *buf, size_t numBytes) +{ + if (connSocket==INVALID_SOCKET) + throw cRuntimeError("cSocketRTScheduler: sendBytes(): no connection"); + + send(connSocket, buf, numBytes, 0); + // TBD check for errors +} + +void cSocketSequentialScheduler::close() +{ + if (connSocket!=INVALID_SOCKET) + { + closesocket(connSocket); + connSocket = INVALID_SOCKET; + } +} + diff --git a/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.h b/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.h new file mode 100644 index 000000000..47c79f806 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/SocketSequentialScheduler.h @@ -0,0 +1,79 @@ +/* + * SocketSequentialScheduler.h + * + * Created on: 3 Feb 2014 + * Author: Michal + */ + +#ifndef SOCKETSEQUENTIALSCHEDULER_H_ +#define SOCKETSEQUENTIALSCHEDULER_H_ + +#include + +#include "SocketDataProvider.h" + +class cSocketSequentialScheduler: public cSequentialScheduler, public cSocketDataProvider { + +protected: + // config + int port; + + cModule *module; + cMessage *notificationMsg; + char *recvBuffer; + int recvBufferSize; + int *numBytesPtr; + int currentSocketCycleCount; + + SOCKET listenerSocket; + SOCKET connSocket; + + int socketCycleCount; + + virtual void setupListener(); + virtual bool receiveWithTimeout(long usec); + +public: + cSocketSequentialScheduler(); + virtual ~cSocketSequentialScheduler(); + + /** + * Called at the beginning of a simulation run. + */ + virtual void startRun(); + + /** + * To be called from the module which wishes to receive data from the + * socket. The method must be called from the module's initialize() + * function. + */ + virtual void setInterfaceModule(cModule *module, cMessage *notificationMsg, + char *recvBuffer, int recvBufferSize, int *numBytesPtr); + + /** + * Called at the end of a simulation run. + */ + virtual void endRun() {}; + + /** + * Recalculates "base time" from current wall clock time. + */ + virtual void executionResumed() {}; + + /** + * Scheduler function -- it comes from cScheduler interface. + */ + virtual cMessage *getNextEvent(); + + /** + * Send on the currently open connection + */ + virtual void sendBytes(const char *buf, size_t numBytes); + + /** + * Close the currently open connection + */ + virtual void close(); +}; + +#endif /* SOCKETSEQUENTIALSCHEDULER_H_ */ diff --git a/jdeeco-simulation-omnet-native/src/VisualizationController.cc b/jdeeco-simulation-omnet-native/src/VisualizationController.cc new file mode 100644 index 000000000..e8780a479 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/VisualizationController.cc @@ -0,0 +1,97 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#include "VisualizationController.h" + +Define_Module(VisualizationController); + +VisualizationController *VisualizationController::instance = NULL; + +VisualizationController::VisualizationController() +{ + if (instance) + error("There can be only one ChannelController instance in the network"); + instance = this; +} + +VisualizationController::~VisualizationController() +{ + instance = NULL; +} + +VisualizationController *VisualizationController::getInstance() +{ + if (!instance) + throw cRuntimeError("ChannelController::getInstance(): there is no ChannelController module in the network"); + return instance; +} + +int VisualizationController::findMobileNode(IMobileApplication* p) +{ + for (int i=0; i<(int)nodeList.size(); i++) + if (nodeList[i] == p) + return i; + return -1; +} + +void VisualizationController::addMobileNode(IMobileApplication* p) +{ + if (findMobileNode(p) == -1) + nodeList.push_back(p); +} + +void VisualizationController::removeMobileNode(IMobileApplication* p) +{ + int k = findMobileNode(p); + if (k != -1) + nodeList.erase(nodeList.begin()+k); +} + +void VisualizationController::initialize() +{ + playgroundLat = simulation.getSystemModule()->par("playgroundLatitude"); + playgroundLon = simulation.getSystemModule()->par("playgroundLongitude"); + KmlHttpServer::getInstance()->addKmlFragmentProvider(this); +} + +void VisualizationController::handleMessage(cMessage *msg) +{ + error("This module does not process messages"); +} + +std::string VisualizationController::getKmlFragment() +{ + std::vector connections; + + std::string fragment; + + for (int i=0; i<(int)nodeList.size(); ++i) + { + for (int j=i+1; j<(int)nodeList.size(); ++j) + { + IMobileApplication *pi = nodeList[i]; + IMobileApplication *pj = nodeList[j]; + double ix = pi->getPositionX(), iy = pi->getPositionY(), jx = pj->getPositionX(), jy = pj->getPositionY(); + if (pi->getTxRange()*pi->getTxRange() > (ix-jx)*(ix-jx)+(iy-jy)*(iy-jy)) { + double ilat = KmlUtil::y2lat(playgroundLat, iy); + double ilon = KmlUtil::x2lon(ilat, playgroundLon, ix); + connections.push_back(KmlUtil::Pt2D(ilon, ilat)); + + double jlat = KmlUtil::y2lat(playgroundLat, jy); + double jlon = KmlUtil::x2lon(jlat, playgroundLon, jx); + connections.push_back(KmlUtil::Pt2D(jlon, jlat)); + } + } + } + fragment += KmlUtil::lines("connectivity_1", connections, "connectivity graph", NULL, "60FFFFFF"); + + return fragment; +} + + diff --git a/jdeeco-simulation-omnet-native/src/VisualizationController.h b/jdeeco-simulation-omnet-native/src/VisualizationController.h new file mode 100644 index 000000000..10350e901 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/VisualizationController.h @@ -0,0 +1,55 @@ +// +// This file is part of an OMNeT++/OMNEST simulation example. +// +// Copyright (C) 2010 OpenSim Ltd. +// +// This file is distributed WITHOUT ANY WARRANTY. See the file +// `license' for details on this and other legal matters. +// + +#ifndef __CHANNELCONTROLLER_H_ +#define __CHANNELCONTROLLER_H_ + +#include +#include "KmlHttpServer.h" +#include "KmlUtil.h" + +/** + * Interface to be implemented by mobile nodes to be able to + * register in ChannelController. + */ +class IMobileApplication +{ + public: + virtual double getPositionX() = 0; + virtual double getPositionY() = 0; + virtual double getTxRange() = 0; +}; + +/** + * This module is responsible for tracking the distance of mobile nodes + * and visualizing the connectivity graph via KML. + */ +class VisualizationController : public cSimpleModule, public IKmlFragmentProvider +{ + protected: + static VisualizationController *instance; + std::vector nodeList; + double playgroundLat; + double playgroundLon; + + virtual void initialize(); + virtual void handleMessage(cMessage *msg); + virtual std::string getKmlFragment(); + int findMobileNode(IMobileApplication* p); + + public: + VisualizationController(); + virtual ~VisualizationController(); + static VisualizationController *getInstance(); + virtual void addMobileNode(IMobileApplication* p); + virtual void removeMobileNode(IMobileApplication* p); + +}; + +#endif diff --git a/jdeeco-simulation-omnet-native/src/config.h b/jdeeco-simulation-omnet-native/src/config.h new file mode 100644 index 000000000..be74cf1c8 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/config.h @@ -0,0 +1,25 @@ +/* + * jDEECoConstants.h + * + * Created on: 23 Jan 2014 + * Author: Michal Kit + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#ifdef _WIN32 + +#ifdef MAKEDLL +#define DLLEXPORT_OR_IMPORT __declspec(dllexport) +#else +#define DLLEXPORT_OR_IMPORT __declspec(dllimport) +#endif + +#else + +#define DLLEXPORT_OR_IMPORT + +#endif + +#endif /* CONFIG_H_ */ diff --git a/jdeeco-simulation-omnet-native/src/simulation.cc b/jdeeco-simulation-omnet-native/src/simulation.cc new file mode 100644 index 000000000..e1da60882 --- /dev/null +++ b/jdeeco-simulation-omnet-native/src/simulation.cc @@ -0,0 +1,531 @@ +#include "cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation.h" + +#include +#include +#include +#include + +#include +#include + +#include "JDEECoModule.h" +#include "cmessage.h" + +#include "opp_ctype.h" +#include "args.h" +#include "distrib.h" +#include "cconfigoption.h" +#include "inifilereader.h" +#include "sectionbasedconfig.h" +#include "appreg.h" +#include "cmodule.h" +#include "fsutils.h" +#include "fnamelisttokenizer.h" +#include "stringutil.h" +#include "fileutil.h" +#include "intxtypes.h" +#include "startup.h" + +USING_NAMESPACE; + +Register_GlobalConfigOption(CFGID_LOAD_LIBS, "load-libs", CFG_FILENAMES, "", + "A space-separated list of dynamic libraries to be loaded on startup. The libraries should be given without the `.dll' or `.so' suffix -- that will be automatically appended."); +Register_GlobalConfigOption(CFGID_CONFIGURATION_CLASS, "configuration-class", + CFG_STRING, "", + "Part of the Envir plugin mechanism: selects the class from which all configuration information will be obtained. This option lets you replace omnetpp.ini with some other implementation, e.g. database input. The simulation program still has to bootstrap from an omnetpp.ini (which contains the configuration-class setting). The class should implement the cConfigurationEx interface."); +Register_GlobalConfigOption(CFGID_USER_INTERFACE, "user-interface", CFG_STRING, + "", + "Selects the user interface to be started. Possible values are Cmdenv and Tkenv. This option is normally left empty, as it is more convenient to specify the user interface via a command-line option or the IDE's Run and Debug dialogs. New user interfaces can be defined by subclassing cRunnableEnvir."); + +class JDEECoRuntime { +public: + jobject host; + JavaVM *jvm; + const char * id; + double firstCallAt; + + JDEECoRuntime(jobject host, JavaVM *jvm, const char *id) { + this->jvm = jvm; + this->host = host; + this->id = id; + this->firstCallAt = -1.0; + } +}; + +// XXX: This should be a hash map. Having it in a vector will be too slow when we have many nodes. +std::vector jDEECoRuntimes; +std::vector jDEECoModules; + +static JDEECoRuntime* findRuntime(const char *id) { + JDEECoRuntime *result = NULL; + + std::cout << "findRuntime: " << id << " Begin" << std::endl; + + std::cout << "findRuntime: jDEECoRuntimes=" << &jDEECoRuntimes << std::endl; + + for (std::vector::iterator it = jDEECoRuntimes.begin(); + it != jDEECoRuntimes.end(); ++it) { + std::cout << "findRuntime: runtime with id " << (*it)->id << std::endl; + if (opp_strcmp((*it)->id, id) == 0) { + result = *it; + break; + } + } + + std::cout << "findRuntime: End" << std::endl; + return result; +} + +static JDEECoRuntime* findRuntime(JNIEnv *env, jstring id) { + JDEECoRuntime *result = NULL; + const char *cstring = env->GetStringUTFChars(id, 0); + + result = findRuntime(cstring); + + env->ReleaseStringUTFChars(id, cstring); + return result; +} + +static JDEECoModule* findModule(JNIEnv *env, jstring id) { + JDEECoModule *result = NULL; + const char *cstring = env->GetStringUTFChars(id, 0); + + for (std::vector::iterator it = jDEECoModules.begin(); + it != jDEECoModules.end(); ++it) { + if (opp_strcmp((*it)->getModuleId(), cstring) == 0) { + result = *it; + break; + } + } + + env->ReleaseStringUTFChars(id, cstring); + return result; +} + +// helper macro +#define CREATE_BY_CLASSNAME(var,classname,baseclass,description) \ + baseclass *var ## _tmp = (baseclass *) createOne(classname); \ + var = dynamic_cast(var ## _tmp); \ + if (!var) \ + throw cRuntimeError("Class \"%s\" is not subclassed from " #baseclass, (const char *)classname); + +static void verifyIntTypes() { +#define VERIFY(t,size) if (sizeof(t)!=size) {printf("INTERNAL ERROR: sizeof(%s)!=%d, please check typedefs in include/inttypes.h, and report this bug!\n\n", #t, size); abort();} + VERIFY(int8, 1); + VERIFY(int16, 2); + VERIFY(int32, 4); + VERIFY(int64, 8); + + VERIFY(uint8, 1); + VERIFY(uint16, 2); + VERIFY(uint32, 4); + VERIFY(uint64, 8); +#undef VERIFY + +#define LL INT64_PRINTF_FORMAT + char buf[32]; + int64 a = 1, b = 2; + sprintf(buf, "%"LL"d %"LL"d", a, b); + if (strcmp(buf, "1 2") != 0) { + printf( + "INTERNAL ERROR: INT64_PRINTF_FORMAT incorrectly defined in include/inttypes.h, please report this bug!\n\n"); + abort(); + } +#undef LL +} + +void simulate(const char * envName, const char * confFile) { + cStaticFlag dummy; + // + // SETUP + // + cSimulation *simulationobject = NULL; + cRunnableEnvir *app = NULL; + SectionBasedConfiguration *bootconfig = NULL; + cConfigurationEx *configobject = NULL; + try { + // construct global lists + ExecuteOnStartup::executeAll(); + + // verify definitions of int64, int32, etc. + verifyIntTypes(); + + // + // First, load the ini file. It might contain the name of the user interface + // to instantiate. + // + + InifileReader *inifile = new InifileReader(); + if (fileExists(confFile)) + inifile->readFile(confFile); + + // activate [General] section so that we can read global settings from it + bootconfig = new SectionBasedConfiguration(); + bootconfig->setConfigurationReader(inifile); + bootconfig->activateConfig("General", 0); + + //load libs + std::vector libs = bootconfig->getAsFilenames( + CFGID_LOAD_LIBS); + for (int k = 0; k < (int) libs.size(); k++) { + ::printf("Loading %s ...\n", libs[k].c_str()); + loadExtensionLibrary(libs[k].c_str()); + } + + // + // Create custom configuration object, if needed. + // + std::string configclass = bootconfig->getAsString( + CFGID_CONFIGURATION_CLASS); + if (configclass.empty()) { + configobject = bootconfig; + } else { + // create custom configuration object + CREATE_BY_CLASSNAME(configobject, configclass.c_str(), + cConfigurationEx, "configuration"); + configobject->initializeFrom(bootconfig); + configobject->activateConfig("General", 0); + delete bootconfig; + bootconfig = NULL; + + // load libs from this config as well + std::vector libs = configobject->getAsFilenames( + CFGID_LOAD_LIBS); + for (int k = 0; k < (int) libs.size(); k++) + loadExtensionLibrary(libs[k].c_str()); + } + + // validate the configuration, but make sure we don't report cmdenv-* keys + // as errors if Cmdenv is absent; same for Tkenv. + std::string ignorablekeys; + if (omnetapps.getInstance()->lookup("Cmdenv") == NULL) + ignorablekeys += " cmdenv-*"; + if (omnetapps.getInstance()->lookup("Tkenv") == NULL) + ignorablekeys += " tkenv-*"; + configobject->validate(ignorablekeys.c_str()); + + // + // Choose and set up user interface (EnvirBase subclass). Everything else + // will be done by the user interface class. + // + const char * appname = envName; + if (appname == NULL || opp_strcmp(appname, "") == 0) + appname = configobject->getAsString(CFGID_USER_INTERFACE).c_str(); + cOmnetAppRegistration *appreg = NULL; + if (!(appname == NULL || opp_strcmp(appname, "") == 0)) { + // look up specified user interface + appreg = + static_cast(omnetapps.getInstance()->lookup( + appname)); + if (!appreg) { + ::printf( + "\n" + "User interface '%s' not found (not linked in or loaded dynamically).\n" + "Available ones are:\n", appname); + cRegistrationList *a = omnetapps.getInstance(); + for (int i = 0; i < a->size(); i++) + ::printf(" %s : %s\n", a->get(i)->getName(), + a->get(i)->info().c_str()); + + throw cRuntimeError("Could not start user interface '%s'", + appname); + } + } else { + // user interface not explicitly selected: pick one from what we have + appreg = cOmnetAppRegistration::chooseBest(); + if (!appreg) + throw cRuntimeError( + "No user interface (Cmdenv, Tkenv, etc.) found"); + } + + // + // Create interface object. + // + ::printf("Setting up %s...\n", appreg->getName()); + app = appreg->createOne(); + } catch (std::exception& e) { + ::fprintf(stderr, "\n Error during startup: %s.\n", e.what()); + if (app) { + delete app; + app = NULL; + } else { + delete bootconfig; + } + } + + // + // RUN + // + try { + if (app) { + simulationobject = new cSimulation("simulation", app); + cSimulation::setActiveSimulation(simulationobject); + app->run(0, NULL, configobject); + } + } catch (std::exception& e) { + ::fprintf(stderr, "\n %s.\n", e.what()); + } + + // + // SHUTDOWN + // + cSimulation::setActiveSimulation(NULL); + delete simulationobject; // will delete app as well + + componentTypes.clear(); + nedFunctions.clear(); + classes.clear(); + enums.clear(); + classDescriptors.clear(); + configOptions.clear(); + omnetapps.clear(); + cSimulation::clearLoadedNedFiles(); +} + +JNIEXPORT jdouble JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeGetCurrentTime( + JNIEnv *env, jobject jsimulation) { + //std::cout << "nativeGetCurrentTime: Begin" << std::endl; + jdouble result = -1.0; + if (cSimulation::getActiveSimulation() != NULL) + result = cSimulation::getActiveSimulation()->getSimTime().dbl(); + //std::cout << "nativeGetCurrentTime: Time is " << result << std::endl; + //std::cout << "nativeGetCurrentTime: End" << std::endl; + return result; +} + +JNIEXPORT void JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeRegister( + JNIEnv *env, jobject jsimulation, jobject object, jstring id) { + std::cout << "nativeRegister: Begin" << std::endl; + + if (findRuntime(env, id) != NULL) { + return; + } + + JavaVM *jvm; + jint status = env->GetJavaVM(&jvm); + if (JNI_OK == status) { + const char *cstring = env->GetStringUTFChars(id, 0); + + jDEECoRuntimes.push_back( + new JDEECoRuntime(env->NewGlobalRef(object), jvm, cstring)); + + findRuntime(env, id); + +// XXX: If simulation is repeated and runtimes are re-registered, then this should be called somewhere in the cleanup +// env->ReleaseStringUTFChars(id, cstring); + std::cout << "nativeRegister: JDEECo runtime created for " << cstring << std::endl; + } else { + std::cout << "nativeRegister: JVM could not be retrieved" << std::endl; + } + std::cout << "nativeRegister: End" << std::endl; +} + +JNIEXPORT void JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeSendPacket( + JNIEnv *env, jobject jsimulation, jstring id, jbyteArray packet, + jstring recipient) { + //std::cout << "nativeSendPacket: Begin" << std::endl; + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + int length = env->GetArrayLength(packet); + jbyte *buffer = env->GetByteArrayElements(packet, 0); + JDEECoPacket *jPacket = new JDEECoPacket(JDEECO_DATA_MESSAGE); + //Setting data + jPacket->setDataArraySize(length); + for (int i = 0; i < length; i++) + jPacket->setData(i, buffer[i]); + const char *cRecipient = env->GetStringUTFChars(recipient, 0); + EV << "OMNET++ ("<< simTime() <<") : " << module->getModuleId() << " sending packet with ID = " << jPacket->getId() << endl; + module->sendPacket(jPacket, cRecipient); + env->ReleaseByteArrayElements(packet, buffer, JNI_ABORT); + env->ReleaseStringUTFChars(recipient, cRecipient); + env->DeleteLocalRef(packet); + } + //std::cout << "nativeSendPacket: End" << std::endl; +} + +JNIEXPORT void JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeRun( + JNIEnv *env, jobject jsimulation, jstring environment, jstring confFile) { + std::cout << "nativeRun: Begin" << std::endl; + const char * cEnv = env->GetStringUTFChars(environment, 0); + const char * cConfFile = env->GetStringUTFChars(confFile, 0); + std::cout << "nativeRun: simulate" << std::endl; + simulate(cEnv, cConfFile); + std::cout << "nativeRun: clearing runtimes" << std::endl; + jDEECoModules.clear(); + jDEECoRuntimes.clear(); + env->ReleaseStringUTFChars(environment, cEnv); + env->ReleaseStringUTFChars(confFile, cConfFile); + std::cout << "nativeRun: End" << std::endl; +} + +JNIEXPORT void JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeCallAt( + JNIEnv *env, jobject jsimulation, jdouble absoluteTime, jstring id) { + //std::cout << "nativeCallAt: Begin" << std::endl; + if (cSimulation::getActiveSimulation() != NULL) { + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + //std::cout << "nativeCallAt: " << (*it)->getModuleId() << " will be called at " << absoluteTime << std::endl; + module->callAt(absoluteTime); + } + } else { + JDEECoRuntime *runtime = findRuntime(env, id); + + if (runtime != NULL) { + //std::cout << "nativeCallAt: " << (*it)->id << " will be first called at " << absoluteTime << std::endl; + runtime->firstCallAt = absoluteTime; + } + } + //std::cout << "nativeCallAt: End" << std::endl; +} + +JNIEXPORT jboolean JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeIsPositionInfoAvailable + (JNIEnv *env, jobject jsimulation, jstring id) { + //std::cout << "nativeIsPositionInfoAvailable: Begin" << std::endl; + jboolean result = JNI_FALSE; + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + result = module->isPositionInfoAvailable() ? JNI_TRUE : JNI_FALSE; + } + + //std::cout << "nativeIsPositionInfoAvailable: End" << std::endl; + return result; +} + +// XXX: These three methods should be replaced by one method that returns a triplet (X,Y,Z) + +JNIEXPORT jdouble JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeGetPositionX + (JNIEnv *env, jobject jsimulation, jstring id) { + + //std::cout << "nativeGetPositionX: Begin" << std::endl; + jdouble result = 0; + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + result = module->getPositionX(); + } + + //std::cout << "nativeGetPositionX: End" << std::endl; + return result; +} + +JNIEXPORT jdouble JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeGetPositionY + (JNIEnv *env, jobject jsimulation, jstring id) { + //std::cout << "nativeGetPositionY: Begin" << std::endl; + jdouble result = 0; + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + result = module->getPositionY(); + } + + //std::cout << "nativeGetPositionY: End" << std::endl; + return result; +} + +JNIEXPORT jdouble JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeGetPositionZ +(JNIEnv *env, jobject jsimulation, jstring id) { + //std::cout << "nativeGetPositionZ: Begin" << std::endl; + jdouble result = 0; + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + result = module->getPositionZ(); + } + + //std::cout << "nativeGetPositionZ: End" << std::endl; + return result; +} + +JNIEXPORT void JNICALL Java_cz_cuni_mff_d3s_deeco_simulation_omnet_OMNetSimulation_nativeSetPosition +(JNIEnv *env, jobject jsimulation, jstring id, jdouble valX, jdouble valY, jdouble valZ) { + JDEECoModule *module = findModule(env, id); + + if (module != NULL) { + module->setPosition(valX, valY, valZ); + } +} + +DLLEXPORT_OR_IMPORT void JDEECoModule::callAt(double absoluteTime) { + //std::cout << "jDEECoCallAt: " << this->jDEECoGetModuleId() << " Begin" << std::endl; + if (currentCallAtTime != absoluteTime && simTime().dbl() < absoluteTime) { + currentCallAtTime = absoluteTime; + cMessage *msg = new cMessage(JDEECO_TIMER_MESSAGE); + currentCallAtMessage = msg; + scheduleAt(absoluteTime, msg); + //std::cout << "jDEECoCallAt: " << this->jDEECoGetModuleId() << " Callback added: " << this->jDEECoGetModuleId() << " for " << absoluteTime << std::endl; + } + //std::cout << "jDEECoCallAt: " << this->jDEECoGetModuleId() << " End" << std::endl; +} + +DLLEXPORT_OR_IMPORT void JDEECoModule::onHandleMessage(cMessage *msg, double rssi) { + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Begin" << std::endl; + JDEECoRuntime* runtime = findRuntime(getModuleId()); + + if (runtime != NULL) { + JNIEnv *env; + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before getting the environment" << std::endl; + runtime->jvm->AttachCurrentThread((void **) &env, NULL); + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before getting jobject class" << std::endl; + jclass cls = env->GetObjectClass(runtime->host); + jmethodID mid; + if (opp_strcmp(msg->getName(), JDEECO_TIMER_MESSAGE) == 0) { + // compare in nanos + if (((long) round(simTime().dbl() * 1000000)) == ((long) round(currentCallAtTime * 1000000))) { + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before getting the \"at\" method reference" << std::endl; + mid = env->GetMethodID(cls, "at", "(D)V"); + if (mid == 0) + return; + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before calling the \"at\" method" << std::endl; + env->CallVoidMethod(runtime->host, mid, currentCallAtTime); + } else { + //Ignore the message as it is not valid any longer. + } + } else if (opp_strcmp(msg->getName(), JDEECO_DATA_MESSAGE) == 0) { + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before getting the \"packetRecived\" method reference" << std::endl; + EV << "OMNET++ ("<< simTime() <<") : " << getModuleId() << " received packet with ID = " << msg->getId() << endl; + mid = env->GetMethodID(cls, "packetReceived", "([BD)V"); + if (mid == 0) + return; + JDEECoPacket *jPacket = check_and_cast(msg); + jbyte *buffer = new jbyte[jPacket->getDataArraySize()]; + for (unsigned int i = 0; i < jPacket->getDataArraySize(); i++) + buffer[i] = jPacket->getData(i); + jbyteArray jArray = env->NewByteArray(jPacket->getDataArraySize()); + if (jArray == NULL) { + std::cout << "onHandleMessage: " << this->getModuleId() << " Cannot create new ByteArray object! Out of memory problem?" << std::endl; + return; + } + env->SetByteArrayRegion(jArray, 0, jPacket->getDataArraySize(), + buffer); + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " Before calling the \"packetRecived\" method" << std::endl; + env->CallVoidMethod(runtime->host, mid, jArray, rssi); + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " After calling the \"packetRecived\" method" << std::endl; + env->DeleteLocalRef(jArray); + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " After deleting the array reference" << std::endl; + delete [] buffer; + } + env->DeleteLocalRef(cls); + } + //std::cout << "jDEECoOnHandleMessage: " << this->jDEECoGetModuleId() << " End" << std::endl; +} + +DLLEXPORT_OR_IMPORT void JDEECoModule::initialize() { + std::cout << "initialize: " << this->getModuleId() << " Begin" << std::endl; + std::cout << "initialize: " << this->getModuleId() << " Initializing jDEECo module: " << this->getModuleId() << std::endl; + if (!initialized) { + JDEECoRuntime *runtime = findRuntime(getModuleId()); + + assert(runtime != NULL); + + if (runtime->firstCallAt >= 0) + callAt(runtime->firstCallAt); + + jDEECoModules.push_back(this); + } + + initialized = true; + std::cout << "initialize: " << this->getModuleId() << " End" << std::endl; +} diff --git a/jdeeco-simulation/mvn-local-repo/README.txt b/jdeeco-simulation/mvn-local-repo/README.txt deleted file mode 100644 index d5022a53a..000000000 --- a/jdeeco-simulation/mvn-local-repo/README.txt +++ /dev/null @@ -1,5 +0,0 @@ -In order to make the jar lib accessible through the local maven repository you need to execute the following command: - -mvn install:install-file -Dfile= -DgroupId= \ - -DartifactId= -Dversion= \ - -Dpackaging= -DlocalRepositoryPath= \ No newline at end of file diff --git a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.jar b/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.jar deleted file mode 100644 index 502a30cbf..000000000 Binary files a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.jar and /dev/null differ diff --git a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.pom b/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.pom deleted file mode 100644 index 1822c12de..000000000 --- a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/0.5.0/matsim-0.5.0.pom +++ /dev/null @@ -1,9 +0,0 @@ - - - 4.0.0 - org.matsim - matsim - 0.5.0 - POM was created from install:install-file - diff --git a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/maven-metadata-local.xml b/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/maven-metadata-local.xml deleted file mode 100644 index bf8f79d50..000000000 --- a/jdeeco-simulation/mvn-local-repo/org/matsim/matsim/maven-metadata-local.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - org.matsim - matsim - - 0.5.0 - - 0.5.0 - - 20140522122038 - - diff --git a/jdeeco-simulation/pom.xml b/jdeeco-simulation/pom.xml index 60d0e0675..6593a1772 100644 --- a/jdeeco-simulation/pom.xml +++ b/jdeeco-simulation/pom.xml @@ -9,8 +9,6 @@ cz.cuni.mff.d3s.jdeeco.simulation - ../dist - simulation.jar src @@ -23,77 +21,6 @@ - - - org.apache.maven.plugins - maven-dependency-plugin - 2.6 - - - copy - install - - copy - - - - - ${project.groupId} - ${project.artifactId} - ${project.version} - ${project.packaging} - ${simulationJar} - ${dist} - - - - - - install - - copy-dependencies - - - ${dist} - compile - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [1.0.0,) - - unpack - - copy-dependencies - - - - - - - - - - - - - @@ -109,8 +36,8 @@ - mvn-local-repo - file://${basedir}/mvn-local-repo + d3s + https://gitlab.d3s.mff.cuni.cz:8443/nexus/content/groups/public/
\ No newline at end of file diff --git a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/omnet/OMNetSimulationRuntimeBuilder.java b/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/omnet/OMNetSimulationRuntimeBuilder.java deleted file mode 100644 index 07a9835eb..000000000 --- a/jdeeco-simulation/src/cz/cuni/mff/d3s/deeco/simulation/omnet/OMNetSimulationRuntimeBuilder.java +++ /dev/null @@ -1,62 +0,0 @@ -package cz.cuni.mff.d3s.deeco.simulation.omnet; - -import java.util.Collection; - -import cz.cuni.mff.d3s.deeco.executor.Executor; -import cz.cuni.mff.d3s.deeco.executor.SameThreadExecutor; -import cz.cuni.mff.d3s.deeco.knowledge.KnowledgeManagerContainer; -import cz.cuni.mff.d3s.deeco.model.runtime.api.RuntimeMetadata; -import cz.cuni.mff.d3s.deeco.network.DirectGossipStrategy; -import cz.cuni.mff.d3s.deeco.network.DirectRecipientSelector; -import cz.cuni.mff.d3s.deeco.network.KnowledgeDataManager; -import cz.cuni.mff.d3s.deeco.network.PublisherTask; -import cz.cuni.mff.d3s.deeco.runtime.RuntimeFramework; -import cz.cuni.mff.d3s.deeco.runtime.RuntimeFrameworkImpl; -import cz.cuni.mff.d3s.deeco.scheduler.Scheduler; -import cz.cuni.mff.d3s.deeco.simulation.CallbackProvider; -import cz.cuni.mff.d3s.deeco.simulation.SimulationHost; -import cz.cuni.mff.d3s.deeco.simulation.scheduler.SimulationScheduler; - -public class OMNetSimulationRuntimeBuilder { - - public RuntimeFramework build(SimulationHost host, CallbackProvider callbackProvider, RuntimeMetadata model, Collection recipientSelectors, DirectGossipStrategy directGossipStrategy) { - if (model == null) { - throw new IllegalArgumentException("Model must not be null"); - } - - // Set up the executor - Executor executor = new SameThreadExecutor(); - - // Set up the simulation scheduler - Scheduler scheduler = new SimulationScheduler(host, callbackProvider); - scheduler.setExecutor(executor); - - // Set up the host container - KnowledgeManagerContainer container = new KnowledgeManagerContainer(); - - KnowledgeDataManager kdManager = new KnowledgeDataManager( - container, - host.getPacketSender(), - model.getEnsembleDefinitions(), - host.getHostId(), - scheduler, recipientSelectors, directGossipStrategy); - - // Bind KnowledgeDataReceiver with PacketDataReceiver - host.getPacketReceiver().setKnowledgeDataReceiver(kdManager); - - // Set up the publisher task - PublisherTask publisherTask = new PublisherTask( - scheduler, - kdManager, - host.getHostId()); - - // Add publisher task to the scheduler - scheduler.addTask(publisherTask); - - return new RuntimeFrameworkImpl(model, scheduler, executor, - container); - } - - - -}