forked and modified initial value for return values and changed timer definition to TIM1 instead of int(1)

This commit is contained in:
willem oldemans
2020-10-01 09:36:42 +02:00
commit 6fab141c7e
181 changed files with 38514 additions and 0 deletions

10
tools/chain.conf Normal file
View File

@@ -0,0 +1,10 @@
# chain.conf
# config file for etherSimulator.pl
# Specify the probability of correct delivery between nodea and nodeb (bidirectional)
# probability:nodea:nodeb:probability
# nodea and nodeb are integers 0 to 255
# probability is a float range 0.0 to 1.0
# In this example, the probability of successful transmission
# between nodes 10 and 2 (and vice versa) is given as 0.5 (ie 50% chance)
probability:10:2:0.5

224
tools/etherSimulator.pl Executable file
View File

@@ -0,0 +1,224 @@
#!/usr/bin/perl
#
# etherSimulator.pl
# Simulates the luminiferous ether for RH_Simulator.
# Connects multiple instances of RH_Simulator clients together and passes
# simulated messages between them.
use Getopt::Long;
use strict;
# Configurable variables
my $help;
my $config;
my $port = 4000;
$port = $main::opt_p
if $main::opt_p;
my $bps = 10000;
$bps = $main::opt_b
if $main::opt_b;
# Config that shows probability of successful transmission between nodes
# Read from config file
my %netconfig;
use warnings;
use POE qw(Component::Server::TCP Filter::Block);
use strict;
my @options =
(
'h' => \$help, # Help, show usage
'c=s' => \$config, # Config file
'b=n' => \$bps, # Bits per second simulated baud rate
'p=n' => \$port, # port number
);
&GetOptions(@options) || &usage;
&usage if $help;
readConfig($config) if defined $config;
sub usage
{
print "usage: $0 [-h] [-c configfile] [-b bitspersec] [-p portnumber]\n";
exit;
}
# config file for etherSimulator.pl
# Specify the probability of correct delivery between nodea and nodeb (bidirectional)
# probability:nodea:nodeb:probability
# nodea and nodeb are integers 0 to 255
# probability is a float range 0.0 to 1.0
# In this example, the probability of successful transmission
# between nodes 10 and 2 (and vice versa) is given as 0.5 (ie 50% chance)
# probability:10:2:0.5
sub readConfig
{
my ($config) = @_;
if (open(CONFIG, $config))
{
while (<CONFIG>)
{
if (/^probability:(\d{1,3}):(\d{1,3}):(\d+(\.\d+))/)
{
$netconfig{$1}{$2} = $3;
$netconfig{$2}{$1} = $3; # Bidirectional
}
}
close(CONFIG);
}
else
{
print STDERR "Could not open config file $config: $!\n";
exit;
}
}
# See RHTcpProtocol.h
# messages to and from us are preceded by the payload length as uint32_t in network byte order
sub encoder
{
my $stuff = shift;
substr($$stuff, 0, 0) = pack('N', length($$stuff));
return;
}
sub decoder
{
my $stuff = shift;
return if (length($$stuff) < 4);
my ($length) = unpack('N', $$stuff);
return if (length($$stuff) < $length+4);
return $length + 4;
}
# Filter to assemble and disassemble messages accordiong to precending length
my $filter = POE::Filter::Block->new( LengthCodec => [ \&encoder, \&decoder ] );
# Message types
# See RH_TcpProtocol.h
my $RH_TCP_MESSAGE_TYPE_NOP = 0; # Not used
my $RH_TCP_MESSAGE_TYPE_THISADDRESS = 1; # Specifies the thisAddress of the connected sketch
my $RH_TCP_MESSAGE_TYPE_PACKET = 2; # Message to/from the connected sketch
my %clients;
# Look up the source and dest nodes in the netconfig and return the 0.0 to 1.0 probability
# of successful delivery
sub probabilityOfSuccessfulDelivery
{
my ($from, $to) = @_;
return $netconfig{$from}{$to}
if exists $netconfig{$from}{$to};
# If no explicit probability, use 1.0 (certainty)
return 1.0;
}
# Return true if the message is simulted to have been received successfully
# taking into account the probability of sucessful delivery
sub willDeliverFromTo
{
my ($from, $to) = @_;
my $prob = probabilityOfSuccessfulDelivery($from, $to);
return 1
if rand() < $prob;
return 0;
}
sub deliverMessages
{
my ($key, $value);
while (($key, $value) = each(%clients))
{
next unless defined $$value{'packet'}; # No packet waiting for delivery
# Find how long since the message was transmitted and see it its time to
# deliver it to the client.
# We are waiting here for the transmission time of the message to elapse
# given the message length and the bits per second
my $elapsed = Time::HiRes::tv_interval([$$value{'packetreceived'}], [Time::HiRes::gettimeofday]);
if ($elapsed > length($$value{'packet'}) * 8 / $bps)
{
$$value{'client'}->put(pack('Ca*', $RH_TCP_MESSAGE_TYPE_PACKET, $$value{'packet'}));
delete $$value{'packet'}; # Delivered, forget it
}
}
}
POE::Session->create(
inline_states => {
_start => sub {
$_[KERNEL]->delay(tick => 1);
},
tick => sub {
deliverMessages();
$_[KERNEL]->delay(tick => 0.001);
},
},
);
POE::Component::Server::TCP->new(
Port => $port,
ClientConnected => sub {
my $client = $_[HEAP]{client};
# Create a new object to hold data about RH_TCP messages to and from this client
$clients{$client} = {'client' => $client};
},
ClientInput => sub {
my $client = $_[HEAP]{client};
my $client_input = $_[ARG0];
my $client_id = $_[ARG1];
my ($length, $type) = unpack('NC', $client_input);
if ($type == $RH_TCP_MESSAGE_TYPE_THISADDRESS)
{
# Client notifies us of its node ID
my ($length, $type, $thisaddress) = unpack('NCC', $client_input);
# Set the client objects thisaddress
$clients{$client}{'thisaddress'} = $thisaddress;
}
elsif ($type == $RH_TCP_MESSAGE_TYPE_PACKET)
{
# New packet for transmission
my ($length, $type, $packet) = unpack('NCa*', $client_input);
# Try to deliver the packet to all the other clients
my ($key, $value);
while (($key, $value) = each(%clients))
{
next if ($key eq $client); # Dont deliver back to the same client
# Check the network config and see if delivery to this node is possible
next unless willDeliverFromTo($clients{$client}{'thisaddress'}, $$value{thisaddress});
# The packet reached this destination, see if it collided with
# another packet
if (defined $$value{'packet'})
{
# Collision with waiting packet, delete it
delete $$value{'packet'};
}
else
{
# New packet, queue it for delivery to the client after the
# nominal transmission time is complete
$$value{'packet'} = $packet;
$$value{'packetreceived'} = Time::HiRes::gettimeofday();
}
}
}
},
ClientDisconnected => sub {
my $client = $_[HEAP]{client};
delete $clients{$client};
},
ClientFilter => $filter, # Handles prepended lengths to
);
POE::Kernel->run;
exit;

13
tools/simBuild Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
#
# simBuild
# build a RadioHead example sketch for running as a simulated process
# on Linux.
#
# usage: simBuild sketchname.pde
# The executable will be saved in the current directory
INPUT=$1
OUTPUT=$(basename $INPUT ".pde")
g++ -g -I . -I RHutil -x c++ $INPUT tools/simMain.cpp RHGenericDriver.cpp RHMesh.cpp RHRouter.cpp RHReliableDatagram.cpp RHDatagram.cpp RH_TCP.cpp RH_Serial.cpp RHCRC.cpp RHutil/HardwareSerial.cpp -o $OUTPUT

71
tools/simMain.cpp Normal file
View File

@@ -0,0 +1,71 @@
// main.cpp
// Lets Arduino RadioHead sketches run within a simulator on Linux as a single process
// Copyright (C) 2014 Mike McCauley
// $Id: simMain.cpp,v 1.2 2014/05/09 05:30:03 mikem Exp mikem $
#include <RadioHead.h>
#if (RH_PLATFORM == RH_PLATFORM_UNIX)
#include <stdio.h>
#include <RHutil/simulator.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
SerialSimulator Serial;
// Functions we expect to find in the sketch
extern void setup();
extern void loop();
// Millis at the start of the process
unsigned long start_millis;
int _simulator_argc;
char** _simulator_argv;
// Returns milliseconds since beginning of day
unsigned long time_in_millis()
{
struct timeval te;
gettimeofday(&te, NULL); // get current time
unsigned long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // caclulate milliseconds
return milliseconds;
}
// Run the Arduino standard functions in the main loop
int main(int argc, char** argv)
{
// Let simulated program have access to argc and argv
_simulator_argc = argc;
_simulator_argv = argv;
start_millis = time_in_millis();
// Seed the random number generator
srand(getpid() ^ (unsigned) time(NULL)/2);
setup();
while (1)
loop();
}
void delay(unsigned long ms)
{
usleep(ms * 1000);
}
// Arduino equivalent, milliseconds since process start
unsigned long millis()
{
return time_in_millis() - start_millis;
}
long random(long from, long to)
{
return from + (random() % (to - from));
}
long random(long to)
{
return random(0, to);
}
#endif