parent
eebca9b33a
commit
35810b1581
51 changed files with 5012 additions and 3108 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,29 +1,91 @@ |
||||
# 1 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
# 1 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
# 2 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" 2 |
||||
|
||||
|
||||
# 4 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" 2 |
||||
|
||||
Socket socket; |
||||
LoRaMQTT mqtt; |
||||
|
||||
void callback(const String& s){ |
||||
Serial.println(s); |
||||
void(* resetFunc) (void) = 0; |
||||
|
||||
void setup() { |
||||
|
||||
Serial.begin(115200); |
||||
|
||||
if (!LoRa.begin(433E6)) { |
||||
Serial.println("Starting LoRa failed!"); |
||||
while (1); |
||||
} |
||||
|
||||
pinMode(A0, 0x0); |
||||
pinMode(A1, 0x0); |
||||
pinMode(A2, 0x0); |
||||
pinMode(A3, 0x0); |
||||
pinMode(4, 0x1); |
||||
|
||||
mqtt.ini(); |
||||
mqtt.subscribe("#"); |
||||
mqtt.onReceived(mqttRes); |
||||
|
||||
Serial.println("started.."); |
||||
|
||||
} |
||||
|
||||
void loop() { |
||||
|
||||
if(millis() > 180000) resetFunc(); |
||||
mqtt.core(); |
||||
} |
||||
|
||||
void setup(){ |
||||
void mqttRes(String subject, String content){ |
||||
Serial.println("res"); |
||||
if(subject == "qos/sync" && content.toInt()>=100 && content.toInt()<200){ |
||||
String s; |
||||
getData(s, content); |
||||
Serial.println(s); |
||||
mqtt.publish("res/json", s); |
||||
} |
||||
if(subject == "ctl/node0/waterSwitch"){ |
||||
if(content == "0") pumpOn(); |
||||
if(content == "1") pumpOff(); |
||||
} |
||||
|
||||
delay(1000); |
||||
resetFunc(); |
||||
|
||||
|
||||
} |
||||
|
||||
|
||||
void getData(String& s, const String& content){ |
||||
s = "{\"t\":\"node0\",\"b\":"; |
||||
s += ((long int)analogRead(A2)*100)/1024; |
||||
s += ",\"w\":"; |
||||
s += (analogRead(A3) > 50) ? 0 : 1; |
||||
s += ",\"T\":"; |
||||
s += (125*analogRead(A1))>>8; |
||||
s += ",\"h\":"; |
||||
s += analogRead(A0); |
||||
s += ",\"s\":"; |
||||
s += 0; |
||||
s += ",\"q\":"; |
||||
s += content; |
||||
s += "}"; |
||||
|
||||
Serial.begin(115200); |
||||
socket.ini(); |
||||
socket.onReceive(callback); |
||||
} |
||||
|
||||
|
||||
void loop(){ |
||||
socket.core(); |
||||
//setInterval([](){
|
||||
// socket.udp("hello socket!!!"+String(random(2000)), [](int e){
|
||||
// Serial.println("send ok"+String(random(2000)));
|
||||
// });
|
||||
//}, 7000);
|
||||
|
||||
|
||||
|
||||
bool pumpOn(){ |
||||
digitalWrite(4, 0x1); |
||||
Serial.println("pumpOn"); |
||||
return true; |
||||
} |
||||
|
||||
bool pumpOff(){ |
||||
digitalWrite(4, 0x0); |
||||
Serial.println("pumpOff"); |
||||
return true; |
||||
} |
||||
|
@ -0,0 +1,87 @@ |
||||
#ifndef __LORA_MATT_H__ |
||||
#define __LORA_MATT_H__ |
||||
|
||||
#define MAX_STRINGVEC_SIZE 2 |
||||
#include "lora-socket.h" |
||||
|
||||
|
||||
class LoRaMQTT{ |
||||
|
||||
public: |
||||
|
||||
inline void ini(){ |
||||
socket.ini(); |
||||
socket.onReceived(_onReceived); |
||||
} |
||||
|
||||
inline void core(){ |
||||
if(isLoopMode){ |
||||
if(socket.isNewMsg()){ |
||||
String msg = "", from = "", to = "", type = ""; |
||||
socket.getNewMsg(msg, from, to, type); |
||||
_onReceived(msg, from, to, type); |
||||
} |
||||
} |
||||
socket.core(); |
||||
} |
||||
|
||||
|
||||
inline void publish(const String& subject, const String& content){ |
||||
String s = subject + "$" + content; |
||||
socket.udp(s); |
||||
} |
||||
|
||||
inline void subscribe(const String& subject){ |
||||
this->_subjects.PushBack(subject); |
||||
} |
||||
|
||||
inline static void onReceived(void (*f)(String, String)){ |
||||
_f = f; |
||||
} |
||||
inline bool isNewMsg(){ |
||||
isLoopMode = true; |
||||
return (newSubject == "") ? false : true; |
||||
}; |
||||
inline void getNewMsg(String& subject, String& content){ |
||||
subject = newSubject; |
||||
content = newContent; |
||||
clearNewMsg(); |
||||
} |
||||
|
||||
|
||||
private: |
||||
static LoRaSocket socket; |
||||
static StringVec _subjects; |
||||
static void (*_f)(String, String); |
||||
static String newSubject, newContent; |
||||
static bool isLoopMode; |
||||
|
||||
inline void clearNewMsg(){ |
||||
newSubject = ""; |
||||
newContent = ""; |
||||
}; |
||||
|
||||
inline static void _onReceived(String msg, String from, String to, String type){ |
||||
|
||||
if(msg.indexOf('$') == -1) return; |
||||
String subject = msg.substring(0, msg.indexOf('$')); |
||||
String content = msg.substring(msg.indexOf('$') + 1, msg.length()); |
||||
|
||||
if(_subjects.Find("#") != -1 || _subjects.Find(subject) != -1){ |
||||
newSubject = subject; |
||||
newContent = content; |
||||
if(!isLoopMode) _f(subject, content); |
||||
} |
||||
}; |
||||
|
||||
|
||||
}; |
||||
|
||||
|
||||
LoRaSocket LoRaMQTT::socket; |
||||
StringVec LoRaMQTT::_subjects; |
||||
void (*LoRaMQTT::_f)(String, String); |
||||
String LoRaMQTT::newSubject = "", LoRaMQTT::newContent = ""; |
||||
bool LoRaMQTT::isLoopMode = false; |
||||
|
||||
#endif //__LORA_MATT_H__
|
@ -0,0 +1,289 @@ |
||||
#ifndef __LORA_SOCKET_H__ |
||||
#define __LORA_SOCKET_H__ |
||||
|
||||
#include <LoRa.h> |
||||
#include "vector.h" |
||||
#include "stringVec.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); |
||||
inline static void onReceived(void (*f)(String, String, String, String)){ |
||||
_f = f; |
||||
}; |
||||
inline bool isNewMsg(){ |
||||
isLoopMode = true; |
||||
return (newType == "") ? false : true; |
||||
}; |
||||
inline const String getNewMsg(){ |
||||
String msg = newMsg; |
||||
clearNewMsg(); |
||||
return msg; |
||||
}; |
||||
inline void getNewMsg(String& msg, String& from, String& to, String& type){ |
||||
msg = newMsg; |
||||
from = newFrom; |
||||
to = newTo; |
||||
type = newType; |
||||
clearNewMsg(); |
||||
}; |
||||
|
||||
private: |
||||
static StringVec tcp_sendingStack, tcp_receiveStack; |
||||
static Vector<unsigned int> tcp_sendingTryTimes; |
||||
static void(*_f)(String, String, String, String); |
||||
static String newMsg, newFrom, newTo, newType; |
||||
static bool isLoopMode; |
||||
inline void clearNewMsg(){ |
||||
newMsg = ""; |
||||
newFrom = ""; |
||||
newTo = ""; |
||||
newType = ""; |
||||
}; |
||||
inline static void _onReceived(const String& msg, const String& from, const String& to, const String& type){ |
||||
newMsg = msg; |
||||
newFrom = from; |
||||
newTo = to; |
||||
newType = type; |
||||
if(!isLoopMode) (*_f)(msg, from, to, type); |
||||
}; |
||||
/* LoRa Functions */ |
||||
static void LoRa_tx_mode(); |
||||
static void LoRa_rx_mode(); |
||||
static void send(const String& s); |
||||
static void send(const char *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 + 1, right); |
||||
}; |
||||
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 + 1, right); |
||||
}; |
||||
inline static const String getType(const String& s){ |
||||
return s.substring(0, s.indexOf('|')); |
||||
}; |
||||
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 + 1, right)); |
||||
}; |
||||
inline static const String getTcpKey(const String& s){ |
||||
int left = s.indexOf('|', s.indexOf('|', s.indexOf('|', s.indexOf('|') + 1) + 1) + 1); |
||||
int right = s.indexOf('|', left + 1); |
||||
return s.substring(left + 1, right); |
||||
}; |
||||
/* 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("tc"+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(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"){ |
||||
rtcp(msg); |
||||
if(tcp_receiveStack.Find(msg) != -1) return; |
||||
_onReceived(getContent(msg), getFromIP(msg), getToIP(msg), "tcp"); |
||||
receiveStackClassify(); |
||||
} |
||||
if(getType(msg) == "rtcp"){ |
||||
removeByKey(getContent(msg)); |
||||
} |
||||
|
||||
} |
||||
|
||||
void LoRaSocket::udp(const String& msg, const String& to){ |
||||
char *c; |
||||
c = (char*)malloc((msg.length()+39)*sizeof(char)); |
||||
sprintf(c, "udp|%s%s|", getIPHeader(to).c_str(), encode(msg).c_str()); |
||||
sprintf(c, "%s%s", c, hash(c).c_str()); |
||||
send(c); |
||||
free(c); |
||||
}; |
||||
|
||||
|
||||
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); |
||||
} |
||||
|
||||
StringVec LoRaSocket::tcp_sendingStack, LoRaSocket::tcp_receiveStack; |
||||
Vector<unsigned int> LoRaSocket::tcp_sendingTryTimes; |
||||
void (*LoRaSocket::_f)(String, String, String, String); |
||||
String LoRaSocket::newMsg = "", LoRaSocket::newFrom = "", LoRaSocket::newTo = "", LoRaSocket::newType = ""; |
||||
bool LoRaSocket::isLoopMode = false; |
||||
|
||||
void LoRaSocket::ini() { |
||||
|
||||
LoRa_rx_mode(); |
||||
} |
||||
|
||||
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 char *s){ |
||||
LoRa_tx_mode(); |
||||
delay(200); |
||||
LoRa.beginPacket();Serial.println(s); |
||||
LoRa.print(s); |
||||
LoRa.endPacket(); |
||||
delay(200); |
||||
LoRa_rx_mode(); |
||||
} |
||||
|
||||
void LoRaSocket::send(const String& s){ |
||||
LoRa_tx_mode(); |
||||
delay(200); |
||||
LoRa.beginPacket();Serial.println(s); |
||||
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((char)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__
|
@ -1,37 +1,107 @@ |
||||
#include <Arduino.h> |
||||
#line 1 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
#line 1 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
#include "socket.hpp" |
||||
|
||||
#define LORA_SOCKET_IP "1.0.0.1" |
||||
#include "lora-mqtt.h" |
||||
|
||||
LoRaMQTT mqtt; |
||||
|
||||
Socket socket; |
||||
void(* resetFunc) (void) = 0; |
||||
|
||||
#line 7 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void callback(const String& s); |
||||
#line 11 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
#line 9 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void setup(); |
||||
#line 19 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
#line 32 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void loop(); |
||||
#line 7 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void callback(const String& s){ |
||||
Serial.println(s); |
||||
#line 38 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void mqttRes(String subject, String content); |
||||
#line 58 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void getData(String& s, const String& content); |
||||
#line 79 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
bool pumpOn(); |
||||
#line 85 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
bool pumpOff(); |
||||
#line 9 "e:\\git\\smart-farming\\opt\\node\\node0\\node0.ino" |
||||
void setup() { |
||||
|
||||
Serial.begin(115200); |
||||
|
||||
if (!LoRa.begin(433E6)) { |
||||
Serial.println("Starting LoRa failed!"); |
||||
while (1); |
||||
} |
||||
|
||||
pinMode(A0, INPUT); |
||||
pinMode(A1, INPUT); |
||||
pinMode(A2, INPUT); |
||||
pinMode(A3, INPUT); |
||||
pinMode(4, OUTPUT); |
||||
|
||||
mqtt.ini(); |
||||
mqtt.subscribe("#"); |
||||
mqtt.onReceived(mqttRes); |
||||
|
||||
Serial.println("started.."); |
||||
|
||||
} |
||||
|
||||
void setup(){ |
||||
void loop() { |
||||
|
||||
if(millis() > 180000) resetFunc(); |
||||
mqtt.core(); |
||||
} |
||||
|
||||
void mqttRes(String subject, String content){ |
||||
Serial.println("res"); |
||||
if(subject == "qos/sync" && content.toInt()>=100 && content.toInt()<200){ |
||||
String s; |
||||
getData(s, content); |
||||
Serial.println(s); |
||||
mqtt.publish("res/json", s); |
||||
} |
||||
if(subject == "ctl/node0/waterSwitch"){ |
||||
if(content == "0") pumpOn(); |
||||
if(content == "1") pumpOff(); |
||||
} |
||||
|
||||
delay(1000); |
||||
resetFunc(); |
||||
|
||||
|
||||
Serial.begin(115200); |
||||
socket.ini(); |
||||
socket.onReceive(callback); |
||||
} |
||||
|
||||
|
||||
void loop(){ |
||||
socket.core(); |
||||
//setInterval([](){
|
||||
// socket.udp("hello socket!!!"+String(random(2000)), [](int e){
|
||||
// Serial.println("send ok"+String(random(2000)));
|
||||
// });
|
||||
//}, 7000);
|
||||
void getData(String& s, const String& content){ |
||||
s = "{\"t\":\"node0\",\"b\":"; |
||||
s += ((long int)analogRead(A2)*100)/1024; |
||||
s += ",\"w\":"; |
||||
s += (analogRead(A3) > 50) ? 0 : 1; |
||||
s += ",\"T\":"; |
||||
s += (125*analogRead(A1))>>8; |
||||
s += ",\"h\":"; |
||||
s += analogRead(A0); |
||||
s += ",\"s\":"; |
||||
s += 0; |
||||
s += ",\"q\":"; |
||||
s += content; |
||||
s += "}"; |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool pumpOn(){ |
||||
digitalWrite(4, HIGH); |
||||
Serial.println("pumpOn"); |
||||
return true; |
||||
} |
||||
|
||||
bool pumpOff(){ |
||||
digitalWrite(4, LOW); |
||||
Serial.println("pumpOff"); |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
Binary file not shown.
@ -0,0 +1,77 @@ |
||||
#ifndef __STRINGVEC__ |
||||
#define __STRINGVEC__ |
||||
|
||||
|
||||
|
||||
#ifndef MAX_STRINGVEC_SIZE |
||||
#define MAX_STRINGVEC_SIZE 2 |
||||
#endif |
||||
|
||||
class StringVec{ |
||||
public:
|
||||
StringVec():_size(0){ |
||||
this->clear(); |
||||
}; |
||||
|
||||
inline void PushBack(const String& ss){ |
||||
if(this->Size() == MAX_STRINGVEC_SIZE){ |
||||
this->shift(); |
||||
} |
||||
this->_s[this->Size()] = ss; |
||||
this->_size ++; |
||||
} |
||||
|
||||
const int Find(const String& ss){ |
||||
for(unsigned i = 0; i < this->Size(); i ++){ |
||||
if(this->_s[i] == ss){ |
||||
return i; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
void Erase(const int& pos){ |
||||
if(pos < 0 || pos >= this->Size()) return; |
||||
for(unsigned int i = pos+1; i < this->Size(); i ++){ |
||||
this->_s[i-1] = this->_s[i]; |
||||
} |
||||
this->_size --; |
||||
} |
||||
|
||||
const String shift(){ |
||||
String s = this->_s[0]; |
||||
if(this->Size() != 0){ |
||||
for(unsigned int i = 1; i < this->Size(); i ++){ |
||||
this->_s[i-1] = this->_s[i]; |
||||
} |
||||
this->_size --; |
||||
} |
||||
return s; |
||||
} |
||||
|
||||
void clear(){ |
||||
for(unsigned int i = 0; i < this->Size(); i ++){ |
||||
this->_s[i] = ""; |
||||
} |
||||
} |
||||
|
||||
inline const int Size(){ |
||||
return this->_size; |
||||
} |
||||
|
||||
|
||||
String& operator[](int i){ |
||||
if(i < 0 || i >= this->Size()) return this->_s[0]; |
||||
return this->_s[i]; |
||||
} |
||||
|
||||
private: |
||||
String _s[MAX_STRINGVEC_SIZE]; |
||||
int _size; |
||||
|
||||
}; |
||||
|
||||
|
||||
|
||||
|
||||
#endif //__STRINGVEC__
|
@ -0,0 +1,87 @@ |
||||
#ifndef __LORA_MATT_H__ |
||||
#define __LORA_MATT_H__ |
||||
|
||||
#define MAX_STRINGVEC_SIZE 2 |
||||
#include "lora-socket.h" |
||||
|
||||
|
||||
class LoRaMQTT{ |
||||
|
||||
public: |
||||
|
||||
inline void ini(){ |
||||
socket.ini(); |
||||
socket.onReceived(_onReceived); |
||||
} |
||||
|
||||
inline void core(){ |
||||
if(isLoopMode){ |
||||
if(socket.isNewMsg()){ |
||||
String msg = "", from = "", to = "", type = ""; |
||||
socket.getNewMsg(msg, from, to, type); |
||||
_onReceived(msg, from, to, type); |
||||
} |
||||
} |
||||
socket.core(); |
||||
} |
||||
|
||||
|
||||
inline void publish(const String& subject, const String& content){ |
||||
String s = subject + "$" + content; |
||||
socket.udp(s); |
||||
} |
||||
|
||||
inline void subscribe(const String& subject){ |
||||
this->_subjects.PushBack(subject); |
||||
} |
||||
|
||||
inline static void onReceived(void (*f)(String, String)){ |
||||
_f = f; |
||||
} |
||||
inline bool isNewMsg(){ |
||||
isLoopMode = true; |
||||
return (newSubject == "") ? false : true; |
||||
}; |
||||
inline void getNewMsg(String& subject, String& content){ |
||||
subject = newSubject; |
||||
content = newContent; |
||||
clearNewMsg(); |
||||
} |
||||
|
||||
|
||||
private: |
||||
static LoRaSocket socket; |
||||
static StringVec _subjects; |
||||
static void (*_f)(String, String); |
||||
static String newSubject, newContent; |
||||
static bool isLoopMode; |
||||
|
||||
inline void clearNewMsg(){ |
||||
newSubject = ""; |
||||
newContent = ""; |
||||
}; |
||||
|
||||
inline static void _onReceived(String msg, String from, String to, String type){ |
||||
|
||||
if(msg.indexOf('$') == -1) return; |
||||
String subject = msg.substring(0, msg.indexOf('$')); |
||||
String content = msg.substring(msg.indexOf('$') + 1, msg.length()); |
||||
|
||||
if(_subjects.Find("#") != -1 || _subjects.Find(subject) != -1){ |
||||
newSubject = subject; |
||||
newContent = content; |
||||
if(!isLoopMode) _f(subject, content); |
||||
} |
||||
}; |
||||
|
||||
|
||||
}; |
||||
|
||||
|
||||
LoRaSocket LoRaMQTT::socket; |
||||
StringVec LoRaMQTT::_subjects; |
||||
void (*LoRaMQTT::_f)(String, String); |
||||
String LoRaMQTT::newSubject = "", LoRaMQTT::newContent = ""; |
||||
bool LoRaMQTT::isLoopMode = false; |
||||
|
||||
#endif //__LORA_MATT_H__
|
@ -0,0 +1,289 @@ |
||||
#ifndef __LORA_SOCKET_H__ |
||||
#define __LORA_SOCKET_H__ |
||||
|
||||
#include <LoRa.h> |
||||
#include "vector.h" |
||||
#include "stringVec.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); |
||||
inline static void onReceived(void (*f)(String, String, String, String)){ |
||||
_f = f; |
||||
}; |
||||
inline bool isNewMsg(){ |
||||
isLoopMode = true; |
||||
return (newType == "") ? false : true; |
||||
}; |
||||
inline const String getNewMsg(){ |
||||
String msg = newMsg; |
||||
clearNewMsg(); |
||||
return msg; |
||||
}; |
||||
inline void getNewMsg(String& msg, String& from, String& to, String& type){ |
||||
msg = newMsg; |
||||
from = newFrom; |
||||
to = newTo; |
||||
type = newType; |
||||
clearNewMsg(); |
||||
}; |
||||
|
||||
private: |
||||
static StringVec tcp_sendingStack, tcp_receiveStack; |
||||
static Vector<unsigned int> tcp_sendingTryTimes; |
||||
static void(*_f)(String, String, String, String); |
||||
static String newMsg, newFrom, newTo, newType; |
||||
static bool isLoopMode; |
||||
inline void clearNewMsg(){ |
||||
newMsg = ""; |
||||
newFrom = ""; |
||||
newTo = ""; |
||||
newType = ""; |
||||
}; |
||||
inline static void _onReceived(const String& msg, const String& from, const String& to, const String& type){ |
||||
newMsg = msg; |
||||
newFrom = from; |
||||
newTo = to; |
||||
newType = type; |
||||
if(!isLoopMode) (*_f)(msg, from, to, type); |
||||
}; |
||||
/* LoRa Functions */ |
||||
static void LoRa_tx_mode(); |
||||
static void LoRa_rx_mode(); |
||||
static void send(const String& s); |
||||
static void send(const char *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 + 1, right); |
||||
}; |
||||
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 + 1, right); |
||||
}; |
||||
inline static const String getType(const String& s){ |
||||
return s.substring(0, s.indexOf('|')); |
||||
}; |
||||
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 + 1, right)); |
||||
}; |
||||
inline static const String getTcpKey(const String& s){ |
||||
int left = s.indexOf('|', s.indexOf('|', s.indexOf('|', s.indexOf('|') + 1) + 1) + 1); |
||||
int right = s.indexOf('|', left + 1); |
||||
return s.substring(left + 1, right); |
||||
}; |
||||
/* 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("tc"+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(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"){ |
||||
rtcp(msg); |
||||
if(tcp_receiveStack.Find(msg) != -1) return; |
||||
_onReceived(getContent(msg), getFromIP(msg), getToIP(msg), "tcp"); |
||||
receiveStackClassify(); |
||||
} |
||||
if(getType(msg) == "rtcp"){ |
||||
removeByKey(getContent(msg)); |
||||
} |
||||
|
||||
} |
||||
|
||||
void LoRaSocket::udp(const String& msg, const String& to){ |
||||
char *c; |
||||
c = (char*)malloc((msg.length()+39)*sizeof(char)); |
||||
sprintf(c, "udp|%s%s|", getIPHeader(to).c_str(), encode(msg).c_str()); |
||||
sprintf(c, "%s%s", c, hash(c).c_str()); |
||||
send(c); |
||||
free(c); |
||||
}; |
||||
|
||||
|
||||
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); |
||||
} |
||||
|
||||
StringVec LoRaSocket::tcp_sendingStack, LoRaSocket::tcp_receiveStack; |
||||
Vector<unsigned int> LoRaSocket::tcp_sendingTryTimes; |
||||
void (*LoRaSocket::_f)(String, String, String, String); |
||||
String LoRaSocket::newMsg = "", LoRaSocket::newFrom = "", LoRaSocket::newTo = "", LoRaSocket::newType = ""; |
||||
bool LoRaSocket::isLoopMode = false; |
||||
|
||||
void LoRaSocket::ini() { |
||||
|
||||
LoRa_rx_mode(); |
||||
} |
||||
|
||||
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 char *s){ |
||||
LoRa_tx_mode(); |
||||
delay(200); |
||||
LoRa.beginPacket();Serial.println(s); |
||||
LoRa.print(s); |
||||
LoRa.endPacket(); |
||||
delay(200); |
||||
LoRa_rx_mode(); |
||||
} |
||||
|
||||
void LoRaSocket::send(const String& s){ |
||||
LoRa_tx_mode(); |
||||
delay(200); |
||||
LoRa.beginPacket();Serial.println(s); |
||||
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((char)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__
|
@ -1,27 +1,90 @@ |
||||
#include "socket.hpp" |
||||
|
||||
#define LORA_SOCKET_IP "1.0.0.1" |
||||
#include "lora-mqtt.h" |
||||
|
||||
LoRaMQTT mqtt; |
||||
|
||||
Socket socket; |
||||
void(* resetFunc) (void) = 0; |
||||
|
||||
void setup() { |
||||
|
||||
Serial.begin(115200); |
||||
|
||||
if (!LoRa.begin(433E6)) { |
||||
Serial.println("Starting LoRa failed!"); |
||||
while (1); |
||||
} |
||||
|
||||
pinMode(A0, INPUT); |
||||
pinMode(A1, INPUT); |
||||
pinMode(A2, INPUT); |
||||
pinMode(A3, INPUT); |
||||
pinMode(4, OUTPUT); |
||||
|
||||
mqtt.ini(); |
||||
mqtt.subscribe("#"); |
||||
mqtt.onReceived(mqttRes); |
||||
|
||||
Serial.println("started.."); |
||||
|
||||
void callback(const String& s){ |
||||
Serial.println(s); |
||||
} |
||||
|
||||
void setup(){ |
||||
void loop() { |
||||
|
||||
if(millis() > 180000) resetFunc(); |
||||
mqtt.core(); |
||||
} |
||||
|
||||
void mqttRes(String subject, String content){ |
||||
Serial.println("res"); |
||||
if(subject == "qos/sync" && content.toInt()>=100 && content.toInt()<200){ |
||||
String s; |
||||
getData(s, content); |
||||
Serial.println(s); |
||||
mqtt.publish("res/json", s); |
||||
} |
||||
if(subject == "ctl/node0/waterSwitch"){ |
||||
if(content == "0") pumpOn(); |
||||
if(content == "1") pumpOff(); |
||||
} |
||||
|
||||
delay(1000); |
||||
resetFunc(); |
||||
|
||||
|
||||
Serial.begin(115200); |
||||
socket.ini(); |
||||
socket.onReceive(callback); |
||||
} |
||||
|
||||
|
||||
void loop(){ |
||||
socket.core(); |
||||
//setInterval([](){
|
||||
// socket.udp("hello socket!!!"+String(random(2000)), [](int e){
|
||||
// Serial.println("send ok"+String(random(2000)));
|
||||
// });
|
||||
//}, 7000);
|
||||
void getData(String& s, const String& content){ |
||||
s = "{\"t\":\"node0\",\"b\":"; |
||||
s += ((long int)analogRead(A2)*100)/1024; |
||||
s += ",\"w\":"; |
||||
s += (analogRead(A3) > 50) ? 0 : 1; |
||||
s += ",\"T\":"; |
||||
s += (125*analogRead(A1))>>8; |
||||
s += ",\"h\":"; |
||||
s += analogRead(A0); |
||||
s += ",\"s\":"; |
||||
s += 0; |
||||
s += ",\"q\":"; |
||||
s += content; |
||||
s += "}"; |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool pumpOn(){ |
||||
digitalWrite(4, HIGH); |
||||
Serial.println("pumpOn"); |
||||
return true; |
||||
} |
||||
|
||||
bool pumpOff(){ |
||||
digitalWrite(4, LOW); |
||||
Serial.println("pumpOff"); |
||||
return true; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,77 @@ |
||||
#ifndef __STRINGVEC__ |
||||
#define __STRINGVEC__ |
||||
|
||||
|
||||
|
||||
#ifndef MAX_STRINGVEC_SIZE |
||||
#define MAX_STRINGVEC_SIZE 2 |
||||
#endif |
||||
|
||||
class StringVec{ |
||||
public:
|
||||
StringVec():_size(0){ |
||||
this->clear(); |
||||
}; |
||||
|
||||
inline void PushBack(const String& ss){ |
||||
if(this->Size() == MAX_STRINGVEC_SIZE){ |
||||
this->shift(); |
||||
} |
||||
this->_s[this->Size()] = ss; |
||||
this->_size ++; |
||||
} |
||||
|
||||
const int Find(const String& ss){ |
||||
for(unsigned i = 0; i < this->Size(); i ++){ |
||||
if(this->_s[i] == ss){ |
||||
return i; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
void Erase(const int& pos){ |
||||
if(pos < 0 || pos >= this->Size()) return; |
||||
for(unsigned int i = pos+1; i < this->Size(); i ++){ |
||||
this->_s[i-1] = this->_s[i]; |
||||
} |
||||
this->_size --; |
||||
} |
||||
|
||||
const String shift(){ |
||||
String s = this->_s[0]; |
||||
if(this->Size() != 0){ |
||||
for(unsigned int i = 1; i < this->Size(); i ++){ |
||||
this->_s[i-1] = this->_s[i]; |
||||
} |
||||
this->_size --; |
||||
} |
||||
return s; |
||||
} |
||||
|
||||
void clear(){ |
||||
for(unsigned int i = 0; i < this->Size(); i ++){ |
||||
this->_s[i] = ""; |
||||
} |
||||
} |
||||
|
||||
inline const int Size(){ |
||||
return this->_size; |
||||
} |
||||
|
||||
|
||||
String& operator[](int i){ |
||||
if(i < 0 || i >= this->Size()) return this->_s[0]; |
||||
return this->_s[i]; |
||||
} |
||||
|
||||
private: |
||||
String _s[MAX_STRINGVEC_SIZE]; |
||||
int _size; |
||||
|
||||
}; |
||||
|
||||
|
||||
|
||||
|
||||
#endif //__STRINGVEC__
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue