Skip to content

Commit

Permalink
Merge branch 'master' of github.com:madhephaestus/SimplePacketComs
Browse files Browse the repository at this point in the history
  • Loading branch information
madhephaestus committed May 2, 2019
2 parents 2f8692e + 2bff4fd commit b8abf75
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.vscode
215 changes: 214 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,215 @@
# SimplePacketComs
A simple packet comms library
A simple packet coms library. This is the definition page and C++ implementation of SimplePacketComs.

# Theory Of Operation

SimplePacketComs is a protocol spec for transmitting data from one endpoint to another. The goal is to allow many different commands to be sent and received on a single communication channel, with an easy to extend framework. The assumptions that we made is that the physical layer will send and receive aligned, checksummed packets of data.

## Packet Structure

Packets consist of 4 bytes to define the command ID and N bytes (detected from the PHY) of data. The Command ID is parsed as a 32 bit unsigned int. The data can be sent as raw bytes or 32 bit floating point numbers.

By convention, a standard packet is 64 bytes. If both sides of an implementation change this, it does not break spec, but for "Simplicity" this is not transmitted in packet data and must be agreed upon ahead of time by both sides of the command stack.

### Byte Packets

An example byte packet from the Game Controller looks like this:

| |ID | byte 0 |byte 1 |byte 2 |byte 3 |byte 4 |byte 5 |byte 6 |byte 7 |byte 8 |byte 9 |byte 10 |byte 11 |byte 12 |byte 13 |byte 14 |byte 15 |byte 16 |byte 17 |byte 18 |byte 19 |
|--- |--- | --- |--- | --- |--- | --- | --- | --- |--- | --- |--- | --- | --- | --- |--- | --- |--- | --- | --- |--- |--- |
| downstream Bytes |4 | 1 | 1 | 1 | 1 | 1 | 1 |1 | 1 | 1 | 1 | 1 | 1 |1 | 1 | 1 | 1 | 1 | 1 |1|1|
| Contents downstream |1970 | Controller ID| JoyXLeft | JoyYLeft | JoyXRight | JoyYRight | TriggerLeft | TriggerRight |PadRight/PadLeft| PadDown/PadUp |--- |--- |ButtonX|ButtonY|ButtonA|ButtonB|ButtonMinus/getButtonPlus|ButtonHome|---|ButtonZLeft|ButtonZRight|
| upstream Bytes |4 | 60 |
| Contents upstream |1970 | Byte data to be printed by the game controller server|


### Float packets

An example float packet from the warehouse robot looks like this:

| |ID | float |float |float |float |float |float |
|--- |--- | --- |--- | --- |--- | --- | --- |
| downstream Bytes |4 | 4 | 4 | 4 | 4 | 4 | 4 |
| Contents downstream |1936 | pickup area | pickup x | pickup z | drop off area | drop off x | drop off z |
| upstream Bytes |4 | 0 |
| Contents upstream |1936 | ---|



# Known Stack implementations

## Arduino

In Library Manager search for SimplePacketComs

## C++

https://github.com/madhephaestus/SimplePacketComs/

## Java
![](https://img.shields.io/nexus/r/https/oss.sonatype.org/com.neuronrobotics/SimplePacketComsJava.svg?style=flat)

# Gradle

```
repositories {
//com.neuronrobotics hosting point
maven { url 'https://oss.sonatype.org/content/repositories/staging/' }
}
dependencies {
compile "com.neuronrobotics:SimplePacketComsJava:SEE BADGE FOR VERSION "
}
```
### Source

https://github.com/madhephaestus/SimplePacketComsJava

## Matlab (Experimental)

https://github.com/WPIRoboticsEngineering/RBE3001_Matlab

# Known Microcontroller Phy's

## MBED C++ USB HID (Example using Mbed HID)

https://github.com/WPIRoboticsEngineering/RBE3001_nucleo_firmware

## Arduino Teensy 3.2-6 HID

In Library Manager search for Teensy32SimplePacketComs

## Arduino ESP32 WiFi UDP

In Library Manager search for Esp32SimplePacketComs


# Code Examples

For a code example, we will use the C++ Stack in Arduino, the Esp32SimplePacketComs Phy, and the BNO055Server on the device side. On the receive side we will use SimplePacketComsJava and a Groovy script to connect to the device.

## Arduino Setup

Install from the Library Manager

```
Esp32SimplePacketComs
SimplePacketComs
BNO055SimplePacketComs
```

Open the Example -> BNO055SimplePacketComs -> BNO055Server and program your ESP32. If you have never used a WiFiManager before, open the serial monitor (make sure no line endings is enabled) and type your Wifi SSID and hit enter. Wait to be prompted for the password. Then type the password and hit enter. Once connected to the Wifi the IP address will be written out to the non-volatile memory. This device will connect automatically from now on.

Get a BNO055 sensor from Adafruit or Digikey and connect it to the I2C bus on your ESP32.

The Arduino is now set up.

## Groovy setup

In BowlerStudio, run https://gist.github.com/5931b62a4f02216136583ec67dd993ff.git BNO055Visualizer.groovy

You will see the device connect and a small servo display on the screen. The orientation of the servo is controlled by the BNO055.
# HOWTO use the C++ stack

## New Servers C++
```
class ExampleServer: public PacketEventAbstract {
public:
// Packet ID needs to be set
ExampleServer() :
PacketEventAbstract(1871) // Address of this event
{
}
//User function to be called when a packet comes in
// Buffer contains data from the packet coming in at the start of the function
// User data is written into the buffer to send it back
void event(float * buffer) {
// read from buffer to get incomming data
// write to buffer to send data back
}
};
UDPSimplePacket coms;
WifiManager manager;
manager.setup();
coms.attach( new ExampleServer());
coms.attach(new NameCheckerServer("MyRobotName"));
while(true){
manager.loop();
if(manager.getState()==Connected)
coms.server();
}
```
## New clients C++
```
WifiManager manager;
manager.setup();
this event, Size of packet
class ExampleClientMessageHandeler: public IPacketResponseEvent {
public:
ExampleClientMessageHandeler();
virtual ~ExampleClientMessageHandeler();
void onResponse(int timeBetweenSendAndRecive){
Serial.println("Responce!");
}
void onTimeout(int timeBetweenSendAndRecive){
Serial.println("Timeout!");
}
};
boolean once = false;
while(true){
manager.loop();
if (manager.getState()==Connected) {
if(!once){
static IPAddress broadcast=WiFi.localIP();// Get the WiFI connection IP address
UDPSimplePacketComs * coms = new UDPSimplePacketComs(&broadcast,true);// Create a Coms device
AbstractPacketType * ExampleClient =new AbstractPacketType(1871, 64);//Create a client for the server above, Address of
ExampleClient->setResponseListener(new ExampleClientMessageHandeler());
coms->addPollingPacket(ExampleClient); // Add the packet to a polling queue
once = true;
}
coms->loop(millis(), 100);// Loop the server and look for responses
}
}
```

# HOWTO Use the Java Stack

## New Clients Java

```
public class ExampleClient extends UDPSimplePacketComs {
private FloatPacketType IMU = new FloatPacketType(1871, 64);
double[] data = new double[15];
public ExampleClient(String name) throws Exception {
super(name);
addPollingPacket(IMU);
addEvent(1871,()->{
readFloats(1871, data);
});
}
public double get(int index){
return data[index];
}
public void send(int index,double d){
IMU.getDownstream()[index]=d;
}
}
```

## New Servers Java

```
public class ExampleServer extends UdpServer {
public ExampleServer(String name, int index) {
super(name);
addServer(new FloatServer(1871) {
public boolean event(float[] packet) {
}
});
}
}
```
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=SimplePacketComs
version=0.0.6
version=0.0.7
author=Kevin Harrington <mad.hephaestus@gmail.com>
maintainer=Kevin Harrington <mad.hephaestus@gmail.com>
sentence=A library to convert byte streams of packets into floats.
Expand Down
47 changes: 28 additions & 19 deletions src/SimplePacketComs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,37 @@ uint32_t SimplePacketComsAbstract::getNumberOfFloatsInPacket() {
return (numberOfBytes / 4) - 1;
}

void SimplePacketComsAbstract::attach(
PacketEventAbstract * eventImplementation) {
fmap.push_back(eventImplementation);

void SimplePacketComsAbstract::attach(PacketEventAbstract * eventImplementation){
fmap[eventImplementation->getId()] = eventImplementation;
}

PacketEventAbstract * SimplePacketComsAbstract::detach(uint32_t id) {
PacketEventAbstract *event = fmap[id];
fmap.erase(id);
return event;
}

/**
* This runs the packet server and calls all events if a backet comes in
*/
void SimplePacketComsAbstract::server() {
if (isPacketAvailible()) {
getPacket(buffer, numberOfBytes);
uint32_t currentId = getIdPointer()[0];
for (std::vector<PacketEventAbstract*>::iterator it = fmap.begin();
it != fmap.end(); ++it) {
if ((*it)->getId() == currentId) {
(*it)->noResponse = false; // reset the response flag
(*it)->event(getDataPointer());
if ((*it)->noResponse == false) // responde unless the no response flag is set
sendPacket(buffer, numberOfBytes);
return; // packet is responded to, fast return
}
}
* This runs the packet server and calls all events if a backet comes in
*/
void SimplePacketComsAbstract::server(){
if(isPacketAvailible()){
getPacket(buffer, numberOfBytes);
uint32_t currentId = getIdPointer()[0];
for (std::map<uint32_t, PacketEventAbstract*>::iterator it = fmap.begin() ; it != fmap.end(); ++it){
if (it->second->getId() == currentId) {
it->second->noResponse = false; // reset the response flag
it->second->event(getDataPointer());

if (it->second->noResponse == false) {
// respond unless the no response flag is set
sendPacket(buffer, numberOfBytes);
}

return; // packet is responded to, fast return
}
}

//printf("\nUnknown packet %i ",currentId);
for (int i = 0; i < 4; i++) {
Expand Down
57 changes: 32 additions & 25 deletions src/SimplePacketComs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define SimplePacketComs
#include <stdint.h>
#include <stdio.h>
#include <vector>
#include <map>
#include <iostream>
#include "PacketEvent.h"
#include "client/AbstractSimpleComsDevice.h"
Expand All @@ -13,9 +13,10 @@

class SimplePacketComsAbstract {
private:
uint32_t numberOfBytes;
uint8_t * buffer;
std::vector<PacketEventAbstract*> fmap;

uint32_t numberOfBytes;
uint8_t * buffer;
std::map<uint32_t, PacketEventAbstract*> fmap;
public:
SimplePacketComsAbstract();
/**
Expand Down Expand Up @@ -45,28 +46,34 @@ class SimplePacketComsAbstract {
*/
uint32_t getNumberOfFloatsInPacket();

/**
* Attach a function to a packet event
*/
void attach(PacketEventAbstract * eventImplementation);
/**
* This runs the packet server and calls all events if a backet comes in
*/
void server();
/**
* This pushes a packet upstream
*/
void push(uint32_t id, float * buffer);

uint32_t * getIdPointer() {
return (uint32_t *) buffer;
}
float * getDataPointer() {
return (float *) (buffer + 4);
}
std::vector<PacketEventAbstract*> * getfMap() {
return &fmap;
}
/**
* Attach a function to a packet event
*/
void attach(PacketEventAbstract * eventImplementation);
/**
* Detach a function from a packet event.
*
* @param id The packet id.
* @return The function that was attached.
*/
PacketEventAbstract * detach(uint32_t id);
/**
* This runs the packet server and calls all events if a backet comes in
*/
void server();
/**
* This pushes a packet upstream
*/
void push(uint32_t id, float * buffer );

uint32_t * getIdPointer(){
return (uint32_t *)buffer;
}
float * getDataPointer(){
return (float *)(buffer+4);
}
std::map<uint32_t, PacketEventAbstract*> * getfMap(){ return &fmap;}

};

Expand Down

0 comments on commit b8abf75

Please sign in to comment.