mirror of https://github.com/IoTcat/sola.git
parent
92577d8e0e
commit
5b36b529a7
15 changed files with 728 additions and 1006 deletions
@ -0,0 +1 @@ |
|||||||
|
./bin/ |
@ -0,0 +1,65 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-20 09:58:28
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-30 12:35:44 |
||||||
|
*/ |
||||||
|
#ifndef __BUZ_H__ |
||||||
|
#define __BUZ_H__ |
||||||
|
|
||||||
|
class Buz{ |
||||||
|
public: |
||||||
|
Buz(const int& pin){ |
||||||
|
this->_pin = pin; |
||||||
|
}; |
||||||
|
~Buz(){}; |
||||||
|
|
||||||
|
void ini() { |
||||||
|
pinMode(this->_pin, OUTPUT); |
||||||
|
this->_fStatus = this->getStatus(); |
||||||
|
}; |
||||||
|
|
||||||
|
void loop(){ |
||||||
|
if(millis() < this->_toT){ |
||||||
|
analogWrite(this->_pin, (int)((float)((this->_toT - millis()) % 3000) * 255 / 3000)); |
||||||
|
this->_status = true; |
||||||
|
}else{ |
||||||
|
analogWrite(this->_pin, 0); |
||||||
|
this->_status = false; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
inline void on(const int& t = 12*60*1000){ |
||||||
|
this->_toT = millis() + t; |
||||||
|
} |
||||||
|
|
||||||
|
inline void off(){ |
||||||
|
this->_toT = 0; |
||||||
|
} |
||||||
|
|
||||||
|
inline void once(const int& times = 4){ |
||||||
|
this->_toT = millis() + 3000 * times; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool getStatus() const{ |
||||||
|
return this->_status; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isStateChange() { |
||||||
|
if(this->_fStatus != this->getStatus()){ |
||||||
|
this->_fStatus = this->getStatus(); |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
static unsigned int _toT; |
||||||
|
unsigned int _pin;
|
||||||
|
bool _status, _fStatus; |
||||||
|
}; |
||||||
|
|
||||||
|
unsigned int Buz::_toT = 0; |
||||||
|
|
||||||
|
#endif //__BUZ_H__
|
@ -0,0 +1,97 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-20 09:58:21
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-30 13:12:01 |
||||||
|
*/ |
||||||
|
#ifndef __LED_H__ |
||||||
|
#define __LED_H__ |
||||||
|
|
||||||
|
class LED { |
||||||
|
public: |
||||||
|
|
||||||
|
LED(const int& pin){ |
||||||
|
this->_pin = pin; |
||||||
|
this->_mode = "on"; |
||||||
|
}; |
||||||
|
~LED(){}; |
||||||
|
|
||||||
|
inline void on(){ |
||||||
|
digitalWrite(this->_pin, HIGH); |
||||||
|
this->_mode = "on"; |
||||||
|
} |
||||||
|
|
||||||
|
inline void off(){ |
||||||
|
digitalWrite(this->_pin, LOW); |
||||||
|
this->_mode = "off"; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool toggle(){ |
||||||
|
digitalWrite(this->_pin, !digitalRead(this->_pin)); |
||||||
|
this->_mode = (digitalRead(this->_pin)) ? "on" : "off"; |
||||||
|
return digitalRead(this->_pin); |
||||||
|
} |
||||||
|
|
||||||
|
inline void ini(){ |
||||||
|
pinMode(this->_pin, OUTPUT); |
||||||
|
this->_fStatus = this->getMode(); |
||||||
|
} |
||||||
|
|
||||||
|
inline void loop() const{ |
||||||
|
if(this->_mode == "on" || this->_mode == "off"){ |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if(this->_mode == "star"){ |
||||||
|
if(millis() % this->_period < this->_period / 2){ |
||||||
|
digitalWrite(this->_pin, HIGH); |
||||||
|
}else{ |
||||||
|
digitalWrite(this->_pin, LOW); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(this->_mode == "breath"){ |
||||||
|
int val; |
||||||
|
if(millis() % this->_period < this->_period / 2){ |
||||||
|
val = millis() % this->_period; |
||||||
|
val = (float)val * 255 / (this->_period / 2); |
||||||
|
}else{ |
||||||
|
val = this->_period - millis() % this->_period; |
||||||
|
val = (float)val * 255 / (this->_period / 2); |
||||||
|
} |
||||||
|
analogWrite(this->_pin, val); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void star(const unsigned int& period = 2000){ |
||||||
|
this->_mode = "star"; |
||||||
|
this->_period = period; |
||||||
|
} |
||||||
|
|
||||||
|
void breath(const unsigned int& period = 3000){ |
||||||
|
this->_mode = "breath"; |
||||||
|
this->_period = period; |
||||||
|
} |
||||||
|
|
||||||
|
inline const String getMode() const{ |
||||||
|
return this->_mode; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isStateChange(){ |
||||||
|
if(this->_fStatus != this->getMode()){ |
||||||
|
this->_fStatus = this->getMode(); |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
unsigned short _pin; |
||||||
|
String _mode, _fStatus; |
||||||
|
unsigned int _period; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
#endif //__LED_H__
|
@ -0,0 +1,107 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-30 13:36:43
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-30 14:17:59 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __LIGHTCTL_H__ |
||||||
|
#define __LIGHTCTL_H__ |
||||||
|
|
||||||
|
class LightCtl{ |
||||||
|
public: |
||||||
|
LightCtl(Relay* _light, LED* _led, Mode* _mode){ |
||||||
|
light = _light; |
||||||
|
led = _led; |
||||||
|
mode = _mode; |
||||||
|
_fStatus = _status; |
||||||
|
}; |
||||||
|
~LightCtl(){ |
||||||
|
delete light, led, mode; |
||||||
|
}; |
||||||
|
|
||||||
|
void on(){ |
||||||
|
if(mode->isOffline()){ |
||||||
|
if(mode->nightMode() == 0){ |
||||||
|
light->off(); |
||||||
|
led->star(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 1){ |
||||||
|
light->on(); |
||||||
|
led->star(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 2){ |
||||||
|
light->off(); |
||||||
|
led->on(); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
if(mode->nightMode() == 0){ |
||||||
|
light->off(); |
||||||
|
led->breath(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 1){ |
||||||
|
light->on(); |
||||||
|
led->breath(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 2){ |
||||||
|
light->off(); |
||||||
|
led->on(); |
||||||
|
} |
||||||
|
} |
||||||
|
_status = true; |
||||||
|
} |
||||||
|
void off(){ |
||||||
|
if(mode->isOffline()){ |
||||||
|
if(mode->nightMode() == 0){ |
||||||
|
light->off(); |
||||||
|
led->star(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 1){ |
||||||
|
light->off(); |
||||||
|
led->star(); |
||||||
|
} |
||||||
|
if(mode->nightMode() == 2){ |
||||||
|
light->off(); |
||||||
|
led->star(); |
||||||
|
} |
||||||
|
}else{ |
||||||
|
light->off(); |
||||||
|
led->off(); |
||||||
|
} |
||||||
|
_status = false; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool toggle(){ |
||||||
|
if(_status){ |
||||||
|
off(); |
||||||
|
}else{ |
||||||
|
on(); |
||||||
|
} |
||||||
|
return _status; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isStateChange(){ |
||||||
|
if(_fStatus != _status){ |
||||||
|
_fStatus = _status; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool getStatus(){ |
||||||
|
return _status; |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
Relay* light; |
||||||
|
LED* led; |
||||||
|
Mode* mode; |
||||||
|
bool _status, _fStatus; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //__LIGHTCTL_H__
|
@ -1,87 +0,0 @@ |
|||||||
#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__
|
|
@ -1,289 +0,0 @@ |
|||||||
#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(); |
|
||||||
}Serial.println(s); |
|
||||||
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__
|
|
@ -0,0 +1,115 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-30 11:14:59
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-30 13:31:16 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __MODE_H__ |
||||||
|
#define __MODE_H__ |
||||||
|
|
||||||
|
class Mode{ |
||||||
|
public: |
||||||
|
Mode() : _isNight(false), _fIsNight(false), _isAuto(true), _fIsAuto(true), \
|
||||||
|
_isMidnight(false), _fIsMidnight(false), _isOffline(true), _fIsOffline(true){}; |
||||||
|
~Mode(){}; |
||||||
|
|
||||||
|
inline void ini() const{ |
||||||
|
} |
||||||
|
inline void begin() const{ |
||||||
|
this->ini(); |
||||||
|
} |
||||||
|
|
||||||
|
inline void core() const{}; |
||||||
|
inline void loop() const{ |
||||||
|
this->core(); |
||||||
|
}; |
||||||
|
|
||||||
|
inline const bool isNight() const{ |
||||||
|
return this->_isNight; |
||||||
|
} |
||||||
|
inline const bool isNight(const bool& state){ |
||||||
|
this->_isNight = state; |
||||||
|
return this->isNight(); |
||||||
|
} |
||||||
|
inline const bool isNightChange(){ |
||||||
|
if(this->_isNight != this->_fIsNight){ |
||||||
|
this->_fIsNight = this->_isNight; |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isAuto() const{ |
||||||
|
return this->_isAuto; |
||||||
|
} |
||||||
|
inline const bool isAuto(const bool& state){ |
||||||
|
this->_isAuto = state; |
||||||
|
return this->isAuto(); |
||||||
|
} |
||||||
|
inline const bool isAutoChange(){ |
||||||
|
if(this->_isAuto != this->_fIsAuto){ |
||||||
|
this->_fIsAuto = this->_isAuto; |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isMidnight() const{ |
||||||
|
return this->_isMidnight; |
||||||
|
} |
||||||
|
inline const bool isMidnight(const bool& state){ |
||||||
|
this->_isMidnight = state; |
||||||
|
return this->isMidnight(); |
||||||
|
} |
||||||
|
inline const bool isMidnightChange(){ |
||||||
|
if(this->_isMidnight != this->_fIsMidnight){ |
||||||
|
this->_fIsMidnight = this->_isMidnight; |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isOffline() const{ |
||||||
|
return this->_isOffline; |
||||||
|
} |
||||||
|
inline const bool isOffline(const bool& state){ |
||||||
|
this->_isOffline = state; |
||||||
|
return this->isOffline(); |
||||||
|
} |
||||||
|
inline const bool isOfflineChange(){ |
||||||
|
if(this->_isOffline != this->_fIsOffline){ |
||||||
|
this->_fIsOffline = this->_isOffline; |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
inline const unsigned short nightMode(){ |
||||||
|
if(!this->isNight() && !this->isMidnight()){ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
if(this->isNight() && !this->isMidnight()){ |
||||||
|
return 1; |
||||||
|
} |
||||||
|
if(this->isMidnight()){ |
||||||
|
return 2; |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private: |
||||||
|
bool _isNight, _isAuto, _isMidnight, _isOffline; |
||||||
|
bool _fIsNight, _fIsAuto, _fIsMidnight, _fIsOffline; |
||||||
|
|
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //__MODE_H__
|
@ -1,125 +0,0 @@ |
|||||||
|
|
||||||
/**
|
|
||||||
* ovo-arduino Main File |
|
||||||
* |
|
||||||
* @category ovo-arduino |
|
||||||
* @package ovo.cpp |
|
||||||
* @copyright Copyright (c) 2019 EEENeko (https://github.com/eeeneko)
|
|
||||||
* @license GNU General Public License 2.0 |
|
||||||
* @version 0.0.1 |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#ifndef _OVO_H |
|
||||||
#define _OVO_H |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Like set Timeout in JS |
|
||||||
* |
|
||||||
* @Author yimian |
|
||||||
* @param auto function (allow Lambda) |
|
||||||
* @param int millisecond to dealy |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
void setTimeout(auto function,const int delay) |
|
||||||
{ |
|
||||||
static bool on = 1; |
|
||||||
if(on == 1){ |
|
||||||
static unsigned long startTime = millis();
|
|
||||||
|
|
||||||
if(millis() - startTime > delay){ |
|
||||||
function(); |
|
||||||
on == 0; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* Like set Interval in JS |
|
||||||
* |
|
||||||
* @Author yimian |
|
||||||
* @param auto function (allow Lambda) |
|
||||||
* @param int millisecond of interval |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
void setInterval(auto function, const int delay) |
|
||||||
{ |
|
||||||
static unsigned long startTime = millis();
|
|
||||||
|
|
||||||
if(millis() - startTime > delay){ |
|
||||||
function(); |
|
||||||
startTime = millis(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Switch between function1 and function2 for delay1 and delay2 |
|
||||||
* |
|
||||||
* @Author yimian |
|
||||||
* @param auto function1 (allow Lambda) |
|
||||||
* @param auto function2 (allow Lambda) |
|
||||||
* @param int millisecond of interval |
|
||||||
* @param int millisecond of interval |
|
||||||
* @return void |
|
||||||
*/ |
|
||||||
void setSwitch(auto function1, auto function2, const int delay1, const int delay2) |
|
||||||
{ |
|
||||||
static unsigned long startTime = millis();
|
|
||||||
|
|
||||||
if(millis() - startTime < delay1){ |
|
||||||
function1(); |
|
||||||
}else if(millis() - startTime >= delay1 && millis() - startTime < delay1 + delay2){ |
|
||||||
function2(); |
|
||||||
}else if(millis() - startTime >= delay1 + delay2){ |
|
||||||
startTime = millis(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make direct voltage change to gradually change |
|
||||||
* |
|
||||||
* @author yimian |
|
||||||
* @category ovo |
|
||||||
* @package ovo |
|
||||||
*/ |
|
||||||
class slowWrite |
|
||||||
{ |
|
||||||
public: |
|
||||||
inline void set(int t_pin, unsigned int t_delay){ |
|
||||||
pin = t_pin; |
|
||||||
delay = t_delay; |
|
||||||
}; |
|
||||||
inline void high(){ |
|
||||||
startTime = millis(); |
|
||||||
state = 1; |
|
||||||
}; |
|
||||||
inline void low(){ |
|
||||||
startTime = millis(); |
|
||||||
state = 0; |
|
||||||
}; |
|
||||||
inline void run(){ |
|
||||||
if(state == 1 && millis() - startTime < delay){ |
|
||||||
analogWrite(pin, ((millis() - startTime) * 255 / delay));Serial.println(((millis() - startTime) * 255 / delay)); |
|
||||||
}else if(state == 0 && millis() - startTime < delay){ |
|
||||||
analogWrite(pin, 255-((millis() - startTime) * 255 / delay));Serial.println(255-((millis() - startTime) * 255 / delay)); |
|
||||||
}else{ |
|
||||||
state = -1; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
private: |
|
||||||
unsigned long startTime; |
|
||||||
int state; |
|
||||||
int pin; |
|
||||||
unsigned int delay;
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif |
|
||||||
|
|
@ -0,0 +1,57 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-20 11:15:20
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-20 11:28:17 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __PIR_H__ |
||||||
|
#define __PIR_H__ |
||||||
|
|
||||||
|
class Pir{ |
||||||
|
public: |
||||||
|
Pir(const int& pin){ |
||||||
|
this->_pin = pin; |
||||||
|
}; |
||||||
|
~Pir(){}; |
||||||
|
|
||||||
|
void ini() { |
||||||
|
pinMode(this->_pin, INPUT); |
||||||
|
this->_fState = this->getState(); |
||||||
|
}; |
||||||
|
void begin() { |
||||||
|
this->ini(); |
||||||
|
}; |
||||||
|
|
||||||
|
void loop(){ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
const bool isPeopleIn(){ |
||||||
|
if(this->_fState == false && this->getState() == true){ |
||||||
|
this->_fState = true; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const bool isPeopleOut(){ |
||||||
|
if(this->_fState == true && this->getState() == false){ |
||||||
|
this->_fState = false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
}; |
||||||
|
|
||||||
|
const bool getState(){ |
||||||
|
return digitalRead(this->_pin); |
||||||
|
}; |
||||||
|
|
||||||
|
private: |
||||||
|
unsigned short _pin; |
||||||
|
bool _fState; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
#endif //__PIR_H__
|
@ -0,0 +1,62 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-30 11:00:00
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-30 12:35:33 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __RELAY_H__ |
||||||
|
#define __RELAY_H__ |
||||||
|
|
||||||
|
class Relay{ |
||||||
|
public: |
||||||
|
Relay(const int& pin, const bool& onStatus = true){ |
||||||
|
this->_pin = pin; |
||||||
|
this->_onStatus = onStatus; |
||||||
|
}; |
||||||
|
~Relay(){}; |
||||||
|
|
||||||
|
inline void ini() { |
||||||
|
pinMode(this->_pin, OUTPUT); |
||||||
|
this->_fStatus = this->getStatus(); |
||||||
|
}; |
||||||
|
inline void begin() { |
||||||
|
this->ini(); |
||||||
|
}; |
||||||
|
inline void core() const{}; |
||||||
|
inline void loop() const{ |
||||||
|
this->core(); |
||||||
|
} |
||||||
|
|
||||||
|
inline void on() const{ |
||||||
|
digitalWrite(this->_pin, _onStatus); |
||||||
|
} |
||||||
|
inline void off() const{ |
||||||
|
digitalWrite(this->_pin, !_onStatus); |
||||||
|
} |
||||||
|
inline const bool toggle() const{ |
||||||
|
digitalWrite(this->_pin, !digitalRead(this->_pin)); |
||||||
|
return this->getStatus(); |
||||||
|
} |
||||||
|
inline const bool getStatus() const{ |
||||||
|
return (digitalRead(this->_pin) == this->_onStatus) ? true : false; |
||||||
|
} |
||||||
|
|
||||||
|
inline const bool isStateChange() { |
||||||
|
if(this->getStatus() != this->_fStatus){ |
||||||
|
this->_fStatus = this->getStatus(); |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
unsigned short _pin; |
||||||
|
bool _onStatus, _fStatus; |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif //__RELAY_H__
|
@ -1,136 +0,0 @@ |
|||||||
#ifndef __SOCKET_HPP_ |
|
||||||
#define __SOCKET_HPP_ |
|
||||||
|
|
||||||
#include <LoRa.h> |
|
||||||
#include <SPI.h> |
|
||||||
#include "ovo.h" |
|
||||||
#include "vector.h" |
|
||||||
|
|
||||||
#ifndef SS |
|
||||||
#define SS 18 |
|
||||||
#endif |
|
||||||
#ifndef RST |
|
||||||
#define RST 14 |
|
||||||
#endif |
|
||||||
#ifndef DI0 |
|
||||||
#define DI0 26 |
|
||||||
#endif |
|
||||||
#ifndef BAND |
|
||||||
#define BAND 433E6 |
|
||||||
#endif |
|
||||||
#ifndef SEND_TIMES |
|
||||||
#define SEND_TIMES 8 |
|
||||||
#endif |
|
||||||
#ifndef SEND_INTERVAL |
|
||||||
#define SEND_INTERVAL 100 |
|
||||||
#endif |
|
||||||
#ifndef TCP_TIMEOUT |
|
||||||
#define TCP_TIMEOUT 1000 |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
#define DEFAULT_SERIAL 115200 |
|
||||||
|
|
||||||
|
|
||||||
class Socket { |
|
||||||
public: |
|
||||||
Socket(){} |
|
||||||
void core(); |
|
||||||
void ini(); |
|
||||||
void onReceive(auto handler); |
|
||||||
void udp(const String& msg, auto callback); |
|
||||||
inline void udp(const String& msg) { |
|
||||||
this->udp(msg, [=](int err) {}); |
|
||||||
}; |
|
||||||
|
|
||||||
private: |
|
||||||
static Vector<int> udp_sendingStack; |
|
||||||
static String cache; |
|
||||||
static void (*callback)(const String& msg); |
|
||||||
void LoRa_rxMode(); |
|
||||||
void LoRa_txMode(); |
|
||||||
void LoRa_sendMessage(const String& message); |
|
||||||
static void _received(int size); |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
Vector<int> Socket::udp_sendingStack; |
|
||||||
String Socket::cache = ""; |
|
||||||
void (*Socket::callback)(const String& msg); |
|
||||||
|
|
||||||
void Socket::ini() { |
|
||||||
|
|
||||||
if(!Serial) Serial.begin(DEFAULT_SERIAL); |
|
||||||
|
|
||||||
//LoRa.setPins(SS, RST, DI0);
|
|
||||||
if (!LoRa.begin(BAND)) { |
|
||||||
Serial.println("Starting LoRa failed!"); |
|
||||||
while(true); |
|
||||||
} |
|
||||||
LoRa.onReceive(this->_received); |
|
||||||
} |
|
||||||
|
|
||||||
void Socket::core() { |
|
||||||
if(LoRa.parsePacket()){ |
|
||||||
Serial.println("new msg in"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void Socket::_received(int size) { |
|
||||||
String message = ""; |
|
||||||
while (LoRa.available()) { |
|
||||||
message += (char)LoRa.read(); |
|
||||||
} |
|
||||||
Serial.println(" "+message); |
|
||||||
if (message == cache) return; |
|
||||||
cache = message; |
|
||||||
if (message.length() == 3) { |
|
||||||
int pos = udp_sendingStack.Find(message.toInt()); |
|
||||||
if (pos != -1) { |
|
||||||
udp_sendingStack.Erase(pos); |
|
||||||
} |
|
||||||
return; |
|
||||||
} |
|
||||||
(*callback)(message.substring(3)); |
|
||||||
} |
|
||||||
|
|
||||||
void Socket::onReceive(auto handler) { |
|
||||||
static auto f = handler; |
|
||||||
this->callback = f; |
|
||||||
} |
|
||||||
|
|
||||||
void Socket::udp(const String& msg, auto callback) { |
|
||||||
int mid = random(100, 1000); |
|
||||||
String s = String(mid) + msg; |
|
||||||
this->udp_sendingStack.PushBack(mid); |
|
||||||
this->LoRa_txMode(); |
|
||||||
for(int i = 0; i < SEND_TIMES; i ++){ |
|
||||||
setTimeout([=](){ |
|
||||||
this->LoRa_sendMessage(s); |
|
||||||
if(i == SEND_TIMES - 1){ |
|
||||||
this->LoRa_rxMode(); |
|
||||||
callback(0); |
|
||||||
} |
|
||||||
}, i*SEND_INTERVAL); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Socket::LoRa_rxMode(){ |
|
||||||
LoRa.receive(); |
|
||||||
} |
|
||||||
|
|
||||||
void Socket::LoRa_txMode(){ |
|
||||||
LoRa.idle(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void Socket::LoRa_sendMessage(const String& message) { |
|
||||||
LoRa.beginPacket(); |
|
||||||
LoRa.print(message); |
|
||||||
LoRa.endPacket(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
#endif //__SOCKET_HPP_
|
|
@ -1,77 +0,0 @@ |
|||||||
#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,91 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-20 10:04:18
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-08-20 10:40:35 |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef __SWI_H__ |
||||||
|
#define __SWI_H__ |
||||||
|
|
||||||
|
class Swi{ |
||||||
|
public: |
||||||
|
Swi(const int& pin0, const int& pin1){ |
||||||
|
_pin0 = pin0; |
||||||
|
_pin1 = pin1; |
||||||
|
};
|
||||||
|
~Swi(){}; |
||||||
|
|
||||||
|
static inline void ini() { |
||||||
|
pinMode(_pin0, INPUT); |
||||||
|
pinMode(_pin1, OUTPUT); |
||||||
|
_fState = state(); |
||||||
|
}; |
||||||
|
|
||||||
|
static inline void begin() { |
||||||
|
ini(); |
||||||
|
}; |
||||||
|
|
||||||
|
static inline void loop(){ |
||||||
|
const bool sta = state(); |
||||||
|
|
||||||
|
if(sta != _fState){ |
||||||
|
if(sta == true){ |
||||||
|
if(_isDefOn) _on(); |
||||||
|
}else{ |
||||||
|
if(_isDefOff) _off(); |
||||||
|
} |
||||||
|
if(_isDefToggle) _toggle(); |
||||||
|
_fState = sta; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static inline void on(const String& event, void (*f)(void)){ |
||||||
|
if(event == "on"){ |
||||||
|
_on = f; |
||||||
|
_isDefOn = true; |
||||||
|
} |
||||||
|
if(event == "off"){ |
||||||
|
_off = f; |
||||||
|
_isDefOff = true; |
||||||
|
} |
||||||
|
if(event == "toggle"){ |
||||||
|
_toggle = f; |
||||||
|
_isDefToggle = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static const bool state(const unsigned int& total = 600, const unsigned int& threshole = 500){ |
||||||
|
unsigned int cnt = 0; |
||||||
|
for(unsigned int i = 0; i < total; i ++){ |
||||||
|
digitalWrite(_pin1, i % 2); |
||||||
|
if(digitalRead(_pin0) == i%2){ |
||||||
|
cnt ++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if(cnt >= threshole){ |
||||||
|
return true; |
||||||
|
}else{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
static unsigned short _pin0, _pin1; |
||||||
|
static bool _fState; |
||||||
|
static bool _isDefOn, _isDefOff, _isDefToggle; |
||||||
|
static void (*_on)(void); |
||||||
|
static void (*_off)(void); |
||||||
|
static void (*_toggle)(void); |
||||||
|
|
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
unsigned short Swi::_pin0, Swi::_pin1; |
||||||
|
bool Swi::_fState, Swi::_isDefOn = false, Swi::_isDefOff = false, Swi::_isDefToggle = false; |
||||||
|
void (*Swi::_on)(void); |
||||||
|
void (*Swi::_off)(void); |
||||||
|
void (*Swi::_toggle)(void); |
||||||
|
|
||||||
|
#endif //__SWI_H__
|
@ -1,269 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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 <stdint.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#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 ParameterType> class Predicate |
|
||||||
{ |
|
||||||
public: |
|
||||||
virtual void operator() (ParameterType ¶m) = 0; |
|
||||||
}; |
|
||||||
|
|
||||||
template <class VectorType> 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<VectorType> &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
|
|
@ -1,46 +1,156 @@ |
|||||||
|
/*
|
||||||
|
* @Author: IoTcat (https://iotcat.me)
|
||||||
|
* @Date: 2019-08-20 09:57:58
|
||||||
|
* @Last Modified by:
|
||||||
|
* @Last Modified time: 2019-09-10 14:44:11 |
||||||
|
*/ |
||||||
|
|
||||||
#define LORA_SOCKET_IP "1.0.0.1" |
#include <PubSubClient.h> |
||||||
#include "lora-mqtt.h" |
#include <ESP8266WiFi.h> |
||||||
|
|
||||||
LoRaMQTT mqtt; |
#include "relay.h" |
||||||
|
|
||||||
void(* resetFunc) (void) = 0; |
const char* ssid = "yimian-iot"; |
||||||
|
const char* password = "1234567890."; |
||||||
|
const char* mqtt_server = "192.168.3.4"; // change this to the mqtt server
|
||||||
|
|
||||||
void setup() { |
const char* topicInCtl = "hass/ctl/wc0/#"; // change this to the outgoing messages
|
||||||
|
const char* topicInRefresh = "hass/refresh"; |
||||||
|
|
||||||
|
const String clientId = "wc0"; |
||||||
|
|
||||||
|
WiFiClient espClient; |
||||||
|
PubSubClient client(espClient); |
||||||
|
|
||||||
|
Relay valve(D5, false); |
||||||
|
|
||||||
|
volatile double waterFlow = 0, markFlow = 0; |
||||||
|
long unsigned int LastSentTime = millis(); |
||||||
|
|
||||||
|
|
||||||
|
void setup() { |
||||||
Serial.begin(115200); |
Serial.begin(115200); |
||||||
|
WiFi.begin(ssid, password); |
||||||
|
|
||||||
|
attachInterrupt(0, pulse, RISING); //DIGITAL Pin 2: Interrupt 0
|
||||||
|
|
||||||
if (!LoRa.begin(433E6)) { |
while (WiFi.status() != WL_CONNECTED) { |
||||||
Serial.println("Starting LoRa failed!"); |
delay(500); |
||||||
while (1); |
Serial.print("."); |
||||||
} |
} |
||||||
|
pinMode(D10, OUTPUT); |
||||||
|
digitalWrite(D10, HIGH); |
||||||
|
Serial.println(""); |
||||||
|
Serial.println("WiFi connected"); |
||||||
|
Serial.println("IP address: "); |
||||||
|
Serial.println(WiFi.localIP()); |
||||||
|
client.setServer(mqtt_server, 1883); // default port, change it...
|
||||||
|
client.setCallback(callback); |
||||||
|
|
||||||
mqtt.ini(); |
valve.ini(); |
||||||
mqtt.subscribe("#"); |
|
||||||
mqtt.onReceived(mqttRes); |
|
||||||
|
|
||||||
Serial.println("started.."); |
|
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
void loop() { |
|
||||||
|
|
||||||
if(millis() > 180000) resetFunc(); |
|
||||||
mqtt.core(); |
void callback(char* topic, byte* payload, unsigned int length) { |
||||||
|
Serial.print("Message arrived ["); |
||||||
|
Serial.print(topic); |
||||||
|
Serial.print("] "); |
||||||
|
String s = ""; |
||||||
|
for (int i = 0; i < length; i++) { |
||||||
|
s += (char)payload[i]; |
||||||
} |
} |
||||||
|
Serial.print(s); |
||||||
|
Serial.println(""); |
||||||
|
|
||||||
|
mqtt_refresh(topic, s); |
||||||
|
mqtt_valve(topic, s); |
||||||
|
mqtt_flowmeter(topic, s); |
||||||
|
} |
||||||
|
|
||||||
|
void reconnect() { |
||||||
|
// Loop until we're reconnected
|
||||||
|
while (!client.connected()) { |
||||||
|
Serial.print("Attempting MQTT connection..."); |
||||||
|
|
||||||
|
// Attempt to connect
|
||||||
|
if (client.connect(clientId.c_str())) { |
||||||
|
Serial.println("connected"); |
||||||
|
// Once connected, publish an announcement...
|
||||||
|
// client.publish(topicOut, "Hello from the Gateway!");
|
||||||
|
// ... and resubscribe
|
||||||
|
client.subscribe(topicInCtl); |
||||||
|
client.subscribe(topicInRefresh); |
||||||
|
} else { |
||||||
|
Serial.print("failed, rc="); |
||||||
|
Serial.print(client.state()); |
||||||
|
Serial.println(" try again in 5 seconds"); |
||||||
|
// Wait 3 seconds before retrying
|
||||||
|
delay(3000); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void pulse() //measure the quantity of square wave
|
||||||
|
{ |
||||||
|
waterFlow += 1.0 / 450.0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
void mqttRes(String subject, String content){ |
|
||||||
Serial.println("res"); |
|
||||||
Serial.println(subject); |
|
||||||
Serial.println(content); |
|
||||||
|
|
||||||
mqtt.publish("res/json", "lalala"); |
|
||||||
|
|
||||||
delay(1000); |
void loop() { |
||||||
resetFunc(); |
|
||||||
|
// mqtt core
|
||||||
|
if (!client.connected()) { |
||||||
|
reconnect(); |
||||||
|
} |
||||||
|
client.loop(); |
||||||
|
|
||||||
|
// component core
|
||||||
|
|
||||||
|
// valve trigger
|
||||||
|
if(valve.isStateChange()){ |
||||||
|
client.publish(String("hass/snsr/"+clientId+"/valve").c_str(), String(valve.getStatus()).c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
if(waterFlow > markFlow + 0.2 && LastSentTime < millis() - 10 * 1000){ |
||||||
|
client.publish(String("hass/snsr/"+clientId+"/flowmeter").c_str(), String(waterFlow - markFlow).c_str()); |
||||||
|
LastSentTime = millis(); |
||||||
|
} |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
|
|
||||||
|
/**** mqtt func ****/ |
||||||
|
|
||||||
|
void mqtt_refresh(const String& subject, const String& content){ |
||||||
|
|
||||||
|
// send all status
|
||||||
|
if(subject == topicInRefresh){ |
||||||
|
client.publish(String("hass/snsr/"+clientId+"/valve").c_str(), String(valve.getStatus()).c_str()); |
||||||
|
client.publish(String("hass/snsr/"+clientId+"/flowmeter").c_str(), String(waterFlow - markFlow).c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
void mqtt_valve(const String& subject, const String& content){ |
||||||
|
if(subject == String("hass/ctl/"+clientId+"/valve")){ |
||||||
|
if(content == "0"){ |
||||||
|
valve.off(); |
||||||
|
} |
||||||
|
if(content == "1"){ |
||||||
|
valve.on(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void mqtt_flowmeter(const String& subject, const String& content){ |
||||||
|
if(subject == String("hass/ctl/"+clientId+"/flowmeter")){ |
||||||
|
client.publish(String("hass/snsr/"+clientId+"/flowmeter").c_str(), String(waterFlow - markFlow).c_str()); |
||||||
|
} |
||||||
|
if(subject == String("hass/ctl/"+clientId+"/flowmeterGotten")){ |
||||||
|
markFlow = waterFlow; |
||||||
|
} |
||||||
|
} |
||||||
|
Loading…
Reference in new issue