From 3c9eba3651f26bc8043355158196d84ca79500a3 Mon Sep 17 00:00:00 2001 From: iotcat Date: Wed, 17 Jul 2019 08:26:18 +0800 Subject: [PATCH] before test --- .gitignore | 1 + lora-socket.h | 240 ++++++++++++++++++++++++++++++++++++++++++ lora-socket.ino | 25 +++++ vector.h | 269 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 535 insertions(+) create mode 100644 .gitignore create mode 100644 lora-socket.h create mode 100644 lora-socket.ino create mode 100644 vector.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fb3ebab --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.vscode/* diff --git a/lora-socket.h b/lora-socket.h new file mode 100644 index 0000000..e74bae9 --- /dev/null +++ b/lora-socket.h @@ -0,0 +1,240 @@ +#ifndef __LORA_SOCKET_H__ +#define __LORA_SOCKET_H__ + +#include +#include "vector.h" + +#ifndef LORA_SOCKET_IP +#define LORA_SOCKET_IP "0.0.0.0" +#endif + +#ifndef MAX_RECEIVE_STACK_SIZE +#define MAX_RECEIVE_STACK_SIZE 5 +#endif + +#ifndef MAX_SEND_STACK_SIZE +#define MAX_SEND_STACK_SIZE 5 +#endif + +#ifndef MAX_TCP_TRY_TIMES +#define MAX_TCP_TRY_TIMES 8 +#endif + + +class LoRaSocket { + public: + LoRaSocket(){} + static void core(); + static void ini(); + static void udp(const String& msg, const String& to = "0.0.0.0"); + static void tcp(const String& msg, const String& to); + static void rtcp(const String& msg); + + static void onReceived(const String& msg, const String& from, const String& to, const String& type){ + + }; + + + private: + static Vector tcp_sendingStack, tcp_receiveStack; + static Vector tcp_sendingTryTimes; + /* LoRa Functions */ + static void LoRa_tx_mode(); + static void LoRa_rx_mode(); + static void send(const String& s); + static const String& receiveMsg(); + /* Package Functions */ + inline static const String& getIPHeader(const String& to = "0.0.0.0"){ + return to + "|" + LORA_SOCKET_IP + "|"; + }; + inline static bool isGoodPackage(const String& s){ + String body = s.substring(0, s.length() - 1); + if(s.substring(s.length() - 1, s.length()) != hash(body)){ + return false; + } + return true; + }; + inline static const String& getToIP(const String& s){ + unsigned short left = s.indexOf('|'); + unsigned short right = s.indexOf('|', left + 1); + return s.substring(left, right - 1); + }; + inline static const String& getFromIP(const String& s){ + unsigned short left = s.indexOf('|', s.indexOf('|') + 1); + unsigned short right = s.indexOf('|', left + 1); + return s.substring(left, right - 1); + }; + inline static const String& getType(const String& s){ + return s.substring(0, s.indexOf('|') - 1); + }; + inline static const String& getContent(const String& s){ + unsigned short left = s.indexOf('|', s.indexOf('|', s.indexOf('|') + 1) + 1); + unsigned short right = s.indexOf('|', left + 1); + return decode(s.substring(left, right - 1)); + }; + inline static const String& getTcpKey(const String& s){ + unsigned short left = s.indexOf('|', s.indexOf('|', s.indexOf('|', s.indexOf('|') + 1) + 1) + 1); + unsigned short right = s.indexOf('|', left + 1); + return decode(s.substring(left, right - 1)); + }; + /* receive Functions */ + static void getMsg(const String& msg); + /* tcp stack functions */ + static void checkSendStack(){ + for(unsigned int i = 0; i < tcp_sendingStack.Size(); i ++){ + send(tcp_sendingStack[i]); + tcp_sendingTryTimes[i] += 1; + + if(tcp_sendingTryTimes[i] >= MAX_TCP_TRY_TIMES){ + tcp_sendingStack.Erase(i); + tcp_sendingTryTimes.Erase(i); + } + } + }; + inline static void receiveStackClassify(){ + if(tcp_receiveStack.Size() > MAX_RECEIVE_STACK_SIZE) tcp_receiveStack.Erase(0); + }; + inline static void sendStackClassify(){ + if(tcp_sendingStack.Size() > MAX_SEND_STACK_SIZE) { + tcp_sendingStack.Erase(0); + tcp_sendingTryTimes.Erase(0); + } + }; + static void removeByKey(const String& key); + /* tools */ + static const String& hash(const String& s); + static const String& encode(const String& s){ + return s; + }; + static const String& decode(const String& s){ + return s; + } + static const String& generateRandomKey(){ + String o = ""; + for(unsigned short i = 0; i < 4; i ++){ + o += char(LoRa.random() % 26 + 97); + } + return o; + } + + /* timer */ + static void setInterval(void (*function)(void), const int delay){ + static unsigned long startTime = millis(); + + if(millis() - startTime > delay){ + (*function)(); + startTime = millis(); + } + } + + +}; + +void LoRaSocket::getMsg(const String& msg){ + if(!isGoodPackage(msg)) return; + if(getToIP(msg) != LORA_SOCKET_IP && getToIP(msg) != "0.0.0.0") return; + + if(getType(msg) == "udp") onReceived(getContent(msg), getFromIP(msg), getToIP(msg), "udp"); + if(getType(msg) == "tcp"){ + if(tcp_receiveStack.Find(msg) != -1) return; + onReceived(getContent(msg), getFromIP(msg), getToIP(msg), "tcp"); + rtcp(msg); + receiveStackClassify(); + } + if(getType(msg) == "rtcp"){ + removeByKey(getContent(msg)); + } + +} + +void LoRaSocket::udp(const String& msg, const String& to){ + String fin = "udp|" + getIPHeader(to) + encode(msg) + "|"; + fin += hash(fin); + send(fin); +}; + + +void LoRaSocket::tcp(const String& msg, const String& to){ + String fin = "tcp|" + getIPHeader(to) + encode(msg) + "|" + generateRandomKey() + "|"; + fin += hash(fin); + tcp_sendingStack.PushBack(fin); + tcp_sendingTryTimes.PushBack(0); + sendStackClassify(); + send(fin); +}; + + +void LoRaSocket::rtcp(const String& msg){ + tcp_receiveStack.PushBack(msg); + String fin = "rtcp|" + getIPHeader(getFromIP(msg)) + getTcpKey(msg) + "|"; + fin += hash(fin); + send(fin); +} + +Vector LoRaSocket::tcp_sendingStack, LoRaSocket::tcp_receiveStack; +Vector LoRaSocket::tcp_sendingTryTimes; + +void LoRaSocket::ini() { + + +} + +void LoRaSocket::core() { + + /* Listen Msg */ + if(LoRa.parsePacket()){ + getMsg(receiveMsg()); + } + + /* check tcp stack */ + setInterval(checkSendStack, 1000); + +} + +void LoRaSocket::LoRa_tx_mode(){ + LoRa.idle(); +} + +void LoRaSocket::LoRa_rx_mode(){ + LoRa.receive(); +} + +void LoRaSocket::send(const String& s){ + LoRa_tx_mode(); + delay(200); + LoRa.beginPacket(); + LoRa.print(s); + LoRa.endPacket(); + delay(200); + LoRa_rx_mode(); +} + + +const String& LoRaSocket::receiveMsg(){ + String s = ""; + while (LoRa.available()) { + s += (char)LoRa.read(); + } + return s; +} + +const String& LoRaSocket::hash(const String& s){ + unsigned char hashVal = 'k'; + for(unsigned short i = 0; i < s.length(); i ++){ + hashVal ^= s.charAt(i); + } + hashVal = hashVal % 26 + 97; + return String(hashVal); +} + + +void LoRaSocket::removeByKey(const String& key){ + for(unsigned int i = 0; i < tcp_sendingStack.Size(); i++){ + if(getTcpKey(tcp_sendingStack[i]) == key) { + tcp_sendingStack.Erase(i); + return; + } + } +} + +#endif //__LORA_SOCKET_H__ \ No newline at end of file diff --git a/lora-socket.ino b/lora-socket.ino new file mode 100644 index 0000000..4af69c1 --- /dev/null +++ b/lora-socket.ino @@ -0,0 +1,25 @@ + + + + +#include + +#define LORA_SOCKET_IP "2.2.2.1" + +#include "lora-socket.h" + + +LoRaSocket socket; + +void setup(){ + + socket.ini(); + socket.tcp("lalalla", "10.2.3.1"); + socket.udp("ll"); +} + + +void loop(){ + + socket.core(); +} \ No newline at end of file diff --git a/vector.h b/vector.h new file mode 100644 index 0000000..9f7ecad --- /dev/null +++ b/vector.h @@ -0,0 +1,269 @@ +/* + * Vector.h + * + * Created on: 05/04/2012 + * Author: tom + * Purpose: To play the part of a mutable array in the absence of the STL. + */ + +#ifndef VECTOR_H +#define VECTOR_H + +#include +#include +#include + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#define SWAP(type, a, b) type tmp ## a = a; a = b; b = tmp ## a; + +template class Predicate +{ +public: + virtual void operator() (ParameterType ¶m) = 0; +}; + +template class Vector +{ + // The address of the first element of the vector + VectorType *begin; + // The address one after the last allocated entry in the underlying array + VectorType *storage; + // The index of the most recent element put in the underlying array - the head + int head; + +public: + // The value that is returned when the caller asks for an element that is out of the bounds of the vector + VectorType OB; + + // We can save a few re-sizings if we know how large the array is likely to grow to be + Vector(int initialSize = 0) + { + begin = new VectorType[initialSize]; //points to the beginning of the new array + head = initialSize - 1; + storage = begin + initialSize; //points to the element one outside of the array (such that end - begin = capacity) + } + + Vector(Vector &obj) + { + begin = new VectorType[0]; // Points to the beginning of the new array, it's zero but this line keeps malloc from seg faulting should we delete begin before resizing it + head = -1; + storage = begin; //points to the element one outside of the array (such that end - begin = capacity) + + *this = obj; + } + + // If there's anything in the vector then delete the array, if there's no array then doing will will cause seg faults + virtual ~Vector() { delete[] begin; } + + Vector &operator=(Vector &obj) + { + // Reallocate the underlying buffer to the same size as the + Resize(obj.Size()); + + for(int i = 0; i < obj.Size(); i++) + (*this)[i] = obj[i]; + + head = obj.head; + + return *this; + } + + void ForEach(Predicate &functor) + { + for(int i = 0; i < Size(); i++) + functor(begin[i]); + } + + // Swaps the underlying array and characteristics of this vector with another of the same type, very quickly + void Swap(Vector &obj) + { + SWAP(int, head, obj.head); + SWAP(VectorType*, begin, obj.begin); + SWAP(VectorType*, storage, obj.storage); + } + + // Checks the entire Vector to see whether a matching item exists. Bear in mind that the VectorType might need to implement + // equality operator (operator==) for this to work properly. + bool Contains(VectorType element) + { + for(int i = 0; i < Size(); i++) + if(operator [](i) == element) + return true; + + return false; + } + + int Find(VectorType element) + { + for(int i = 0; i < Size(); i++) + if(operator [](i) == element) + return i; + + return -1; + } + + void PushBack(VectorType element) { PushBack(&element, 1); } + + void PushBack(const VectorType *elements, int len) + { + // If the length plus this's size is greater than the capacity, reallocate to that size. + if(len + Size() > Capacity()) + ReAllocate(MAX(Size() + len, Size() * 2)); + + int append = MIN(storage - begin - head - 1, len), prepend = len - append; + + // memcpy the data starting at the head all the way up to the last element *(storage - 1) + memcpy((begin + head + 1), elements, sizeof(VectorType) * append); + + // If there's still data to copy memcpy whatever remains, starting at the first element *(begin) until the end of data. The first step will have ensured + // that we don't crash into the tail during this process. + memcpy(begin,(elements + append), sizeof(VectorType) * prepend); + + // Re-recalculate head and size. + head += len; + } + + void Erase(unsigned int position) { Erase(position, position + 1); } + + // Erase an arbitrary section of the vector from first up to last minus one. Like the stl counterpart, this is pretty labour intensive so go easy on it. + void Erase(int first, int last) + { + // For this we'll set the value of the array at first to the value of the array at last plus one. We'll do that all the way up to toIndex + for(int i = 0; i < (Size() - first); i++) + { + // If by trying to fill in the next element with the ones ahead of it we'll be running off the end of the vector, stop. + if((i + last) > (Size() - 1)) + break; + + begin[first + i] = begin[last + i]; + } + + // Adjust the head to reflect the new size + head -= last - first; + } + + // Remove the most recent element in the array + void PopBack() + { + if(Size() > 0) + head--; + } + + // Empty the vector, or to be precise - forget the fact that there was ever anything in there. + void Clear() { head = -1; } + + // Returns a bool indicating whether or not there are any elements in the array + bool Empty() { return head == -1; } + + // Returns the oldest element in the array (the one added before any other) + VectorType const &Back() { return *begin; } + + // Returns the newest element in the array (the one added after every other) + VectorType const &Front() { return begin[head]; } + + // Returns the nth element in the vector + VectorType &operator[](int n) + { + if(n < Size()) + return begin[n]; + else + return OB; + } + + // Returns a pointer such that the vector's data is laid out between ret to ret + size + VectorType *Data() { return begin; } + + // Recreates the vector to hold len elements, all being copies of val + void Assign(int len, const VectorType &val) + { + delete[] begin; + + // Allocate an array the same size as the one passed in + begin = new VectorType[len]; + storage = begin + len; + + // Refresh the head and tail, assuming the array is in order, which it really has to be + head = len - 1; + + for(int i = 0 ; i < Size(); i++) + begin[i] = val; + } + + // Recreates the vector using an external array + void Assign(VectorType *array, int len) + { + delete[] begin; + + // Allocate an array the same size as the one passed in + begin = new VectorType[len]; + storage = begin + len; + + // Refresh the head and tail, assuming the array is in order, which it really has to be + head = len - 1; + + // Copy over the memory + memcpy(begin, array, sizeof(VectorType) * len); + } + + // Returns the number of elements that the vector will support before needing resizing + int Capacity() { return (storage - begin); } + + // Returns the number of elements in vector + int Size() { return head + 1; } + + // Requests that the capacity of the allocated storage space for the elements + // of the vector be at least enough to hold size elements. + void Reserve(unsigned int size) + { + if(size > Capacity()) + ReAllocate(size); + } + + // Resizes the vector + void Resize(unsigned int size) + { + // If necessary, resize the underlying array to fit the new size + if(size > Capacity()) + ReAllocate(size); + + // Now revise the head and size (tail needn't change) to reflect the new size + head = size - 1; + } + +private: + + void ReAllocate(unsigned int size) + { + // Just in case we're re-allocating less room than we had before, make sure that we don't overrun the buffer by trying to write more elements than + // are now possible for this vector to hold. + if(Size() > (int)size) + head = size - 1; + + // Allocate an array twice the size of that of the old + VectorType *_begin = new VectorType[size]; + VectorType *_storage = _begin + size; + + int _head = Size() - 1; + + // Copy across all the old array's data and rearrange it! + for(int i = 0; i < Size(); i++) + _begin[i] = (*this)[i]; + + // Free the old memory + delete[] begin; + + // Redirect the old array to point to the new one + begin = _begin; + storage = _storage; + head = _head; + } +}; + +#endif // VECTOR_H \ No newline at end of file