public WirelessNetworkSimulation(WirelessNetwork baseNetwork, int?seed = null) { RandomSeed = seed == null?SeedingRandom.Next() : seed.Value; r = new Random(RandomSeed); Network = baseNetwork; foreach (var n in Network.Nodes) { Type t = Assembly.GetExecutingAssembly().GetType(n.NodeType); SimulatedNode simNode = (SimulatedNode)t.GetConstructor(new Type[] { }).Invoke(new object[] { }); simNode.ParentSimulation = this; simNode.SourceNode = n; simNode.MyID = SimulationNodes.Count; WirelessSimulationNode sn = new WirelessSimulationNode() { NetworkNode = n, Node = simNode }; SimulationNodes.Add(sn); } }
public static WirelessUnitTests[] FindUnitTests() { List <WirelessUnitTests> outTests = new List <WirelessUnitTests>(); Type[] nodeTypes = SimulatedNode.FindSimulatedNodeTypes(); foreach (var node in nodeTypes) { List <WirelessUnitTest> tests = new List <WirelessUnitTest>(); foreach (var method in node.GetMethods()) { WirelessUnitTestAttribute attribute = method.GetCustomAttribute <WirelessUnitTestAttribute>(); if (attribute != null) { // Todo: Verify that test is static, and accepts a single parameter taking WirelessUnitTestInstance. tests.Add(new WirelessUnitTest() { UnitTestAttribute = attribute, UnitTestMethod = method, NodeType = node }); } } if (tests.Count > 0) { outTests.Add(new WirelessUnitTests() { NodeType = node, UnitTestMethods = tests.ToArray() }); } } return(outTests.ToArray()); }
public SimulationEvent(double start, SimulatedNode node, EventType t, object context = null, double end = double.MaxValue) { StartTime = start; EndTime = end; Origin = node; Type = t; EventContext = context; }
public void SetButtonState(SimulatedNode n, bool state, int index = 0) { n.PastEvents.Append(new SimulationEvent(CurrentTime, n, EventType.ButtonChange, new ButtonEventContext() { Index = index, Pressed = state })); n.ButtonState[index] = state; ((ISimulatedDevice)n).InputEvent(index, state); }
internal void NodeSetTimer(SimulatedNode n, double time, Action callback) { if (n.TimerEvent != null) { PendingEvents.Remove(n.TimerEvent); n.TimerEvent = null; } var context = new TimerEventContext() { Callback = callback, Time = time }; n.PastEvents.Append(new SimulationEvent(CurrentTime, n, EventType.TimerSet, context)); if (callback != null) { n.TimerEvent = new SimulationEvent(CurrentTime + time, n, EventType.TimerComplete, context); PendingEvents.Insert(n.TimerEvent); } }
bool NodeIsReceiving(SimulatedNode n) { if (n.ReceiverCurrentContext is bool) { return((bool)n.ReceiverCurrentContext); } var context = n.ReceiverCurrentContext as ReceiverPollingContext; if (context != null) { double timeSinceEvent = CurrentTime - n.ReceiverStateChangeTime; double pollCycleLength = context.TimeOn + context.TimeOff; // Find offset in receive cycle. double cycleOffset = timeSinceEvent - Math.Floor(timeSinceEvent / pollCycleLength) * pollCycleLength; // Does the offset in the polling cycle fall in the on time? return(cycleOffset < context.TimeOn); } throw new Exception("Invalid state for receiver context"); }
public static WirelessReport[] FindReports() { List <WirelessReport> outReports = new List <WirelessReport>(); Type[] nodeTypes = SimulatedNode.FindSimulatedNodeTypes(); foreach (var node in nodeTypes) { foreach (var method in node.GetMethods()) { WirelessReportAttribute attribute = method.GetCustomAttribute <WirelessReportAttribute>(); if (attribute != null) { // Todo: Verify that test is static, and accepts a single parameter taking WirelessUnitTestInstance. outReports.Add(new WirelessReport() { NodeType = node, ReportAttribute = attribute, ReportMethod = method }); } } } return(outReports.ToArray()); }
public SimulationEvent FindFirstNodeEvent(SimulatedNode node, double exclusiveStartTime, double inclusiveEndTime, Func <SimulationEvent, bool> filter = null) { foreach (var e in node.PastEvents.Events) { if (e.StartTime <= exclusiveStartTime) { continue; } if (e.StartTime > inclusiveEndTime) { break; } if (!filter(e)) { continue; } // Found an event that matches the criteria return(e); } return(null); }
internal void NodeSendPacket(SimulatedNode n, object packet, double preDelay) { WirelessPacket wp = new WirelessPacket() { StartTime = CurrentTime + preDelay, Origin = n, PacketContents = packet }; // Compute how long the packet is being transmitted for double transmitSpeed = 2000000; int packetBits = 18 * 8; double packetTime = packetBits / (transmitSpeed * n.DeviceTimingSkew); wp.EndTime = wp.StartTime + packetTime; n.PastEvents.Append(new SimulationEvent(CurrentTime, n, EventType.Packet, wp, end: wp.EndTime)); // Find nodes that are in range foreach (var sn in SimulationNodes) { // For each node, // Determine whether the node is listening when the packet starts if (sn.Node == n) { continue; // Don't send to self. } // Future: deal with Z differences Vector v = new Vector(sn.NetworkNode.X - n.SourceNode.X, sn.NetworkNode.Y - n.SourceNode.Y); double distance = v.Length; if (distance > Network.BaseTransmitRange) { continue; // Node out of range. } const double TransmitPropogationSpeed = 300000000; // Speed of RF propogation in air (Close enough) WirelessPacketTransmission t = new WirelessPacketTransmission() { Packet = wp, Receiver = sn.Node, ReceiveSuccess = true, SignalLevel = 0, WirelessDelay = distance / TransmitPropogationSpeed }; // Add a random spike noise check to occasionally drop the packet regardless of other factors. double randomNoiseChance = 0.01; // 1% of packets drop due to random environmental noise if (NextRandom() <= randomNoiseChance) { t.ReceiveSuccess = false; } // Assign a "received signal level" to this packet, and check against a random noise floor (some packets will not be received due to environmental factors) // Signal level can be attenuated by walls in the future, and can be used for overlap checks. // for now, give signal level between 0 (distance 0) and -80 (distance full) t.SignalLevel = 0 - 80 * (distance / Network.BaseTransmitRange); // Seperately randomly drop packets based on distance. if (NextRandom() < (distance / Network.BaseTransmitRange) * 0.7) { // 70% chance to fail receive at max range. t.ReceiveSuccess = false; } // Check whether this packet transmit window overlaps other packets, if so drop both packets (for now) foreach (var otherPacket in sn.Node.InFlightPackets) { if (t.Overlaps(otherPacket)) { t.ReceiveSuccess = false; t.Collision = true; otherPacket.ReceiveSuccess = false; otherPacket.Collision = true; } } // Check whether the target node is receiving at time of packet start // Note: this actually uses the current time (ignores air propogation time, which is negligible) if (!NodeIsReceiving(sn.Node)) { // Node is not receiving, would miss the packet. t.ReceiveSuccess = false; } // Queue this pending packet (end transmission, and in node pending list) PendingEvents.Insert(new SimulationEvent(t.EndTime, sn.Node, EventType.PacketComplete, t)); sn.Node.InFlightPackets.Add(t); } }
internal void NodeSetLed(SimulatedNode n, Color c) { n.LedColor = c; n.PastEvents.Append(new SimulationEvent(CurrentTime, n, EventType.LedChange, c)); LedStateChanged?.Invoke(); }
internal void NodeSetReceiverState(SimulatedNode n, object stateContext) { n.PastEvents.Append(new SimulationEvent(CurrentTime, n, EventType.PowerState, stateContext)); n.ReceiverStateChangeTime = CurrentTime; n.ReceiverCurrentContext = stateContext; }
public SimulationEvent FindFirstLedColor(SimulatedNode node, double exclusiveStartTime, double inclusiveEndTime, Func <Color, bool> filter = null) { return(FindFirstNodeEvent(node, exclusiveStartTime, inclusiveEndTime, (e) => e.Type == EventType.LedChange && (filter == null || filter((Color)e.EventContext)))); }
public SimulationEvent FindFirstReceivedPacket(SimulatedNode node, double exclusiveStartTime, double inclusiveEndTime, Func <SimulationEvent, bool> filter = null) { // Note StartTime for PacketComplete event is the time the packet was received. return(FindFirstNodeEvent(node, exclusiveStartTime, inclusiveEndTime, (e) => e.Type == EventType.PacketComplete && ((WirelessPacketTransmission)e.EventContext).ReceiveSuccess && (filter == null || filter(e)))); }
void InitComboBox() { comboBox.Items.Clear(); comboBox.Items.Add(new ComboBoxItem() { Content = "Move", DataContext = new ActionContext() { MouseMove = MoveMouseMove, MouseDown = MoveMouseDown, MouseUp = MoveMouseUp } }); comboBox.Items.Add(new ComboBoxItem() { Content = "Delete Node", DataContext = new ActionContext() { MouseMove = MoveHighlightNode, MouseDown = DeleteMouseDown, MouseUp = DeleteMouseUp } }); InteractItem = (new ComboBoxItem() { Content = "Interact with Node", DataContext = new ActionContext() { MouseMove = MoveHighlightNode, MouseDown = InteractMouseDown, MouseUp = InteractMouseUp } }); comboBox.Items.Add(InteractItem); comboBox.Items.Add(new Separator()); // Add nodes ComboBoxItem firstItem = null; foreach (var type in SimulatedNode.FindSimulatedNodeTypes()) { ComboBoxItem item = new ComboBoxItem() { Content = $"Add Node: {type.Name}", DataContext = new ActionContext() { MouseMove = MoveHighlightNode, MouseDown = AddMouseDown, MouseUp = AddMouseUp, AddNodeType = type } }; if (firstItem == null) { firstItem = item; } comboBox.Items.Add(item); } // If there is a node, select the first node. if (firstItem != null) { comboBox.SelectedItem = firstItem; } }
internal void BindNode(DebugTimeWindow timeline, SimulatedNode node) { Timeline = timeline; Node = node; InvalidateVisual(); }