master
iotcat 5 years ago
parent eebca9b33a
commit 35810b1581
  1. 2
      opt/gateway/LoRa_GateWay_esp32/LoRa_GateWay_esp32.ino
  2. BIN
      opt/node/node0/.vscode/bin/core/CDC.cpp.o
  3. BIN
      opt/node/node0/.vscode/bin/core/HardwareSerial.cpp.o
  4. BIN
      opt/node/node0/.vscode/bin/core/HardwareSerial0.cpp.o
  5. BIN
      opt/node/node0/.vscode/bin/core/HardwareSerial1.cpp.o
  6. BIN
      opt/node/node0/.vscode/bin/core/HardwareSerial2.cpp.o
  7. BIN
      opt/node/node0/.vscode/bin/core/HardwareSerial3.cpp.o
  8. BIN
      opt/node/node0/.vscode/bin/core/IPAddress.cpp.o
  9. BIN
      opt/node/node0/.vscode/bin/core/PluggableUSB.cpp.o
  10. BIN
      opt/node/node0/.vscode/bin/core/Print.cpp.o
  11. BIN
      opt/node/node0/.vscode/bin/core/Stream.cpp.o
  12. BIN
      opt/node/node0/.vscode/bin/core/Tone.cpp.o
  13. BIN
      opt/node/node0/.vscode/bin/core/USBCore.cpp.o
  14. BIN
      opt/node/node0/.vscode/bin/core/WInterrupts.c.o
  15. BIN
      opt/node/node0/.vscode/bin/core/WMath.cpp.o
  16. BIN
      opt/node/node0/.vscode/bin/core/WString.cpp.o
  17. BIN
      opt/node/node0/.vscode/bin/core/abi.cpp.o
  18. BIN
      opt/node/node0/.vscode/bin/core/core.a
  19. BIN
      opt/node/node0/.vscode/bin/core/hooks.c.o
  20. BIN
      opt/node/node0/.vscode/bin/core/main.cpp.o
  21. BIN
      opt/node/node0/.vscode/bin/core/new.cpp.o
  22. BIN
      opt/node/node0/.vscode/bin/core/wiring.c.o
  23. BIN
      opt/node/node0/.vscode/bin/core/wiring_analog.c.o
  24. BIN
      opt/node/node0/.vscode/bin/core/wiring_digital.c.o
  25. BIN
      opt/node/node0/.vscode/bin/core/wiring_pulse.c.o
  26. BIN
      opt/node/node0/.vscode/bin/core/wiring_shift.c.o
  27. BIN
      opt/node/node0/.vscode/bin/libraries/LoRa/LoRa.cpp.o
  28. BIN
      opt/node/node0/.vscode/bin/libraries/SPI/SPI.cpp.o
  29. BIN
      opt/node/node0/.vscode/bin/node0.ino.elf
  30. 1141
      opt/node/node0/.vscode/bin/node0.ino.hex
  31. 1141
      opt/node/node0/.vscode/bin/node0.ino.with_bootloader.hex
  32. 92
      opt/node/node0/.vscode/bin/preproc/ctags_target_for_gcc_minus_e.cpp
  33. 87
      opt/node/node0/.vscode/bin/sketch/lora-mqtt.h
  34. 289
      opt/node/node0/.vscode/bin/sketch/lora-socket.h
  35. 110
      opt/node/node0/.vscode/bin/sketch/node0.ino.cpp
  36. 7
      opt/node/node0/.vscode/bin/sketch/node0.ino.cpp.d
  37. BIN
      opt/node/node0/.vscode/bin/sketch/node0.ino.cpp.o
  38. 77
      opt/node/node0/.vscode/bin/sketch/stringVec.h
  39. 87
      opt/node/node0/lora-mqtt.h
  40. 289
      opt/node/node0/lora-socket.h
  41. 95
      opt/node/node0/node0.ino
  42. 77
      opt/node/node0/stringVec.h
  43. BIN
      opt/station.zip
  44. 9
      opt/station/.vscode/bin/preproc/ctags_target_for_gcc_minus_e.cpp
  45. 23
      opt/station/.vscode/bin/sketch/station.ino.cpp
  46. BIN
      opt/station/.vscode/bin/sketch/station.ino.cpp.o
  47. BIN
      opt/station/.vscode/bin/station.ino.elf
  48. 2284
      opt/station/.vscode/bin/station.ino.hex
  49. 2284
      opt/station/.vscode/bin/station.ino.with_bootloader.hex
  50. 13
      opt/station/station.ino
  51. 13
      web/index.html

@ -38,7 +38,7 @@ const char* ssid = "yimian-iot";
const char* password = "1234567890.";
const char* mqtt_server = "192.168.1.102";//change this to the mqtt server
char* topicIn="qos/sync";//change this to the outgoing messages
char* topicIn="#";//change this to the outgoing messages
String cache_mqtt_publish = "";
String cache_mqtt_subject = "";

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;
}

@ -12,8 +12,9 @@ e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\node0.ino.cpp.o: \
C:\Program\ Files\ (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h \
C:\Program\ Files\ (x86)\Arduino\hardware\arduino\avr\variants\eightanaloginputs/pins_arduino.h \
C:\Program\ Files\ (x86)\Arduino\hardware\arduino\avr\variants\eightanaloginputs/../standard/pins_arduino.h \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\socket.hpp \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\lora-mqtt.h \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\lora-socket.h \
E:\OneDrive\pc\document\Arduino\libraries\LoRa\src/LoRa.h \
C:\Program\ Files\ (x86)\Arduino\hardware\arduino\avr\libraries\SPI\src/SPI.h \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\ovo.h \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\vector.h
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\vector.h \
e:\git\smart-farming\opt\node\node0\.vscode\bin\sketch\stringVec.h

@ -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.

@ -19,6 +19,7 @@ LoRaMQTT mqtt;
BME280 bme;
GY30 gy;
void (* resetFunc)(void) = 0;
void setup() {
uint8_t osrs_t = 1; //Temperature oversampling x 1
@ -38,6 +39,7 @@ void setup() {
pinMode(A1, 0x0);
pinMode(A3, 0x0);
pinMode(A7, 0x0);
Wire.begin();
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
@ -52,16 +54,19 @@ void setup() {
bme.writeReg(0xF4,ctrl_meas_reg);
bme.writeReg(0xF5,config_reg);
bme.readTrim();
Serial.println("started..");
}
void loop() {
if(millis() > 180000) resetFunc();
mqtt.core();
}
void mqttRes(String subject, String content){
if(subject == "qos/sync"){
if(subject == "qos/sync" && content.toInt()>=0 && content.toInt()<100){
String s;
getData(s, content);
//data = getJson();
@ -72,6 +77,8 @@ void mqttRes(String subject, String content){
mqtt.publish("res/json", s);
}
delay(1000);
resetFunc();
}

@ -10,7 +10,7 @@
//const size_t capacity = JSON_OBJECT_SIZE(15);
//DynamicJsonDocument data(capacity);
#define LORA_SOCKET_IP "1.0.0.2"
#define LORA_SOCKET_IP "1.0.0.0"
#include "lora-mqtt.h"
LoRaMQTT mqtt;
@ -19,16 +19,17 @@ LoRaMQTT mqtt;
BME280 bme;
GY30 gy;
void (* resetFunc)(void) = 0;
#line 21 "e:\\git\\smart-farming\\opt\\station\\station.ino"
#line 22 "e:\\git\\smart-farming\\opt\\station\\station.ino"
void setup();
#line 55 "e:\\git\\smart-farming\\opt\\station\\station.ino"
#line 59 "e:\\git\\smart-farming\\opt\\station\\station.ino"
void loop();
#line 61 "e:\\git\\smart-farming\\opt\\station\\station.ino"
#line 66 "e:\\git\\smart-farming\\opt\\station\\station.ino"
void mqttRes(String subject, String content);
#line 76 "e:\\git\\smart-farming\\opt\\station\\station.ino"
#line 83 "e:\\git\\smart-farming\\opt\\station\\station.ino"
void getData(String& s, const String& content);
#line 21 "e:\\git\\smart-farming\\opt\\station\\station.ino"
#line 22 "e:\\git\\smart-farming\\opt\\station\\station.ino"
void setup() {
uint8_t osrs_t = 1; //Temperature oversampling x 1
uint8_t osrs_p = 1; //Pressure oversampling x 1
@ -47,6 +48,7 @@ void setup() {
pinMode(A1, INPUT);
pinMode(A3, INPUT);
pinMode(A7, INPUT);
Wire.begin();
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
@ -60,17 +62,20 @@ void setup() {
bme.writeReg(0xF2,ctrl_hum_reg);
bme.writeReg(0xF4,ctrl_meas_reg);
bme.writeReg(0xF5,config_reg);
bme.readTrim();
bme.readTrim();
Serial.println("started..");
}
void loop() {
if(millis() > 180000) resetFunc();
mqtt.core();
}
void mqttRes(String subject, String content){
if(subject == "qos/sync"){
if(subject == "qos/sync" && content.toInt()>=0 && content.toInt()<100){
String s;
getData(s, content);
//data = getJson();
@ -81,6 +86,8 @@ void mqttRes(String subject, String content){
mqtt.publish("res/json", s);
}
delay(1000);
resetFunc();
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -8,7 +8,7 @@
//const size_t capacity = JSON_OBJECT_SIZE(15);
//DynamicJsonDocument data(capacity);
#define LORA_SOCKET_IP "1.0.0.2"
#define LORA_SOCKET_IP "1.0.0.0"
#include "lora-mqtt.h"
LoRaMQTT mqtt;
@ -17,6 +17,7 @@ LoRaMQTT mqtt;
BME280 bme;
GY30 gy;
void (* resetFunc)(void) = 0;
void setup() {
uint8_t osrs_t = 1; //Temperature oversampling x 1
@ -36,6 +37,7 @@ void setup() {
pinMode(A1, INPUT);
pinMode(A3, INPUT);
pinMode(A7, INPUT);
Wire.begin();
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
@ -49,17 +51,20 @@ void setup() {
bme.writeReg(0xF2,ctrl_hum_reg);
bme.writeReg(0xF4,ctrl_meas_reg);
bme.writeReg(0xF5,config_reg);
bme.readTrim();
bme.readTrim();
Serial.println("started..");
}
void loop() {
if(millis() > 180000) resetFunc();
mqtt.core();
}
void mqttRes(String subject, String content){
if(subject == "qos/sync"){
if(subject == "qos/sync" && content.toInt()>=0 && content.toInt()<100){
String s;
getData(s, content);
//data = getJson();
@ -70,6 +75,8 @@ void mqttRes(String subject, String content){
mqtt.publish("res/json", s);
}
delay(1000);
resetFunc();
}

@ -18,28 +18,28 @@
</h4><h4>humidity: <span id="sta-humidity"></span>
&nbsp;&nbsp;rainfall: <span id="sta-rainfall"></span> &nbsp;&nbsp;CO: <span id="sta-co"></span>
</h4><h4> NH3: <span id="sta-nh3"></span> &nbsp;&nbsp;airpressure: <span id="sta-airpressure"></span></h4>
<button id="sta-charge">charge battery</button> <button class="refresh">refresh data</button>
<button id="sta-charge">charge battery</button> <button class="refresh station">refresh data</button>
</div>
<HR style="border:1 dashed #987cb9" width="80%" color=#987cb9 SIZE=1></HR>
<div style="margin:auto;">
<h3>Node0 <span id="node0-datetime"></span></h3>
<h4>status: <span id="node0-status"></span> &nbsp;&nbsp;latency: <span id="node0-qos"></span>ms &nbsp;&nbsp;battery: <span id="node0-batterylevel"></span>%</h4>
<h4>switch: <span id="node0-waterswitch"></span> &nbsp;temperature: <span id="node0-temperature"></span> &nbsp;humidity: <span id="node0-humidity"></span></h4>
<button id="node0-swibtn">open switch</button> <button id="node0-charge">charge battery</button> <button class="refresh">refresh data</button>
<button id="node0-swibtn">open switch</button> <button id="node0-charge">charge battery</button> <button class="refresh node0">refresh data</button>
</div>
<HR style="border:1 dashed #987cb9" width="80%" color=#987cb9 SIZE=1></HR>
<div style="margin:auto;">
<h3>Node1 <span id="node1-datetime"></span></h3>
<h4>status: <span id="node1-status"></span> &nbsp;&nbsp;latency: <span id="node1-qos"></span>ms &nbsp;&nbsp;battery: <span id="node1-batterylevel"></span>%</h4>
<h4>switch: <span id="node1-waterswitch"></span> &nbsp;temperature: <span id="node1-temperature"></span> &nbsp;humidity: <span id="node1-humidity"></span></h4>
<button id="node1-swibtn">open switch</button> <button id="node1-charge">charge battery</button> <button class="refresh">refresh data</button>
<button id="node1-swibtn">open switch</button> <button id="node1-charge">charge battery</button> <button class="refresh node1">refresh data</button>
</div>
<HR style="border:1 dashed #987cb9" width="80%" color=#987cb9 SIZE=1></HR>
<div style="margin:auto;">
<h3>waterSys <span id="waterSys-datetime"></span></h3>
<h4>status: <span id="waterSys-status"></span> &nbsp;&nbsp;latency: <span id="waterSys-qos"></span>ms</h4>
<h4>pump0: <span id="waterSys-pump0"></span> &nbsp;&nbsp;pump1: <span id="waterSys-pump1"></span></h4>
<button id="waterSys-pump0btn">open pump0</button> <button id="waterSys-pump1btn">open pump1</button> <button class="refresh">refresh data</button>
<button id="waterSys-pump0btn">open pump0</button> <button id="waterSys-pump1btn">open pump1</button> <button class="refresh waterSys">refresh data</button>
</div>
<script>
@ -57,7 +57,10 @@ var page = {
};
/* request */
$('.refresh').attr('onClick', '$.get("https://smartfarm.yimian.xyz/api/refresh");');
$('.refresh.station').attr('onClick', '$.get("https://smartfarm.yimian.xyz/api/refresh?t=station");');
$('.refresh.node0').attr('onClick', '$.get("https://smartfarm.yimian.xyz/api/refresh?t=node0");');
$('.refresh.node1').attr('onClick', '$.get("https://smartfarm.yimian.xyz/api/refresh?t=node1");');
$('.refresh.waterSys').attr('onClick', '$.get("https://smartfarm.yimian.xyz/api/refresh?t=waterSys");');
setInterval(function(){
$('span').css('color', '#980000');

Loading…
Cancel
Save