340 lines
11 KiB
C++
340 lines
11 KiB
C++
#include <ArduinoJson.h>
|
|
#include <rtl_433_ESP.h>
|
|
//#include <RCSwitch.h>
|
|
#include <Wire.h>
|
|
#include <BME280I2C.h>
|
|
#include <EnvironmentCalculations.h>
|
|
#include "Dictionary.h"
|
|
|
|
#ifndef RF_MODULE_FREQUENCY
|
|
# define RF_MODULE_FREQUENCY 433.92
|
|
#endif
|
|
|
|
#define _DICT_PACK_STRUCTURES
|
|
|
|
#ifndef LED_BUILTIN
|
|
#define LED_BUILTIN 12
|
|
#endif
|
|
#define LED LED_BUILTIN
|
|
|
|
#define RCSWITCH_PIN 43
|
|
|
|
CC1101 radiotx = RADIO_LIB_MODULE;
|
|
//RCSwitch mySwitch = RCSwitch();
|
|
|
|
|
|
#define JSON_MSG_BUFFER 512
|
|
#define MINDELAY 10L
|
|
//#define ALTITUDE 150.0
|
|
#define ALTITUDE 210.0
|
|
#define DELAYLOCALSENSORS 60L
|
|
//#define DELAYKAKUSEND 750L
|
|
|
|
Dictionary<String, unsigned long> d1;
|
|
|
|
char messageBuffer[JSON_MSG_BUFFER];
|
|
|
|
rtl_433_ESP rf; // use -1 to disable transmitter
|
|
|
|
BME280I2C bme;
|
|
bool sensors_enabled;
|
|
|
|
int count = 0;
|
|
unsigned long lastrcv = 0;
|
|
|
|
//unsigned long kakucode = 0;
|
|
//bool kakucmd = false;
|
|
|
|
uint32_t lastts_localsensors = 0;
|
|
|
|
void rtl_433_Callback(char* message) {
|
|
//Serial.println("RTL433 Callback");
|
|
JsonDocument jsonDocument;
|
|
deserializeJson(jsonDocument,message);
|
|
//logJsonAll(jsonDocument);
|
|
logJson(jsonDocument);
|
|
count++;
|
|
lastrcv = millis();
|
|
}
|
|
|
|
JsonDocument analyzeTH_type1(JsonArray payloadrh) {
|
|
JsonDocument doc;
|
|
doc["battery_ok"] = payloadrh[0].as<unsigned char>() & 0b00000001;
|
|
int16_t payloadtemp = payloadrh[4].as<unsigned char>();
|
|
payloadtemp += payloadrh[3].as<unsigned char>() << 8;
|
|
doc["temperature_C"] = payloadtemp / 100.0;
|
|
//doc["moisture"] = payloadrh[5].as<int>();
|
|
uint16_t payloadmoisture = payloadrh[6].as<unsigned char>();
|
|
payloadmoisture += payloadrh[5].as<unsigned char>() << 8;
|
|
doc["moisture"] = payloadmoisture;
|
|
doc["battery_ok"] = payloadrh[0].as<unsigned char>() & 0b00000001;
|
|
uint16_t payloadbat = payloadrh[2].as<unsigned char>();
|
|
payloadbat += payloadrh[1].as<unsigned char>() << 8;
|
|
doc["battery_V"] = ((payloadbat & 0b1111111110000000) >> 7) / 100.0;
|
|
doc["battery_percent"] = (payloadbat & 0b0000000001111111);
|
|
return doc;
|
|
}
|
|
|
|
JsonDocument analyzeTH_type2(JsonArray payloadrh) {
|
|
JsonDocument doc;
|
|
uint8_t errcode = payloadrh[1].as<unsigned char>();
|
|
doc["errcode"] = errcode;
|
|
if(errcode == 0) {
|
|
int16_t payloadtemp = payloadrh[3].as<unsigned char>();
|
|
payloadtemp += payloadrh[2].as<unsigned char>() << 8;
|
|
doc["temperature_C"] = payloadtemp / 100.0;
|
|
uint8_t payloadhumidity = payloadrh[4].as<unsigned char>();
|
|
doc["humidity"] = payloadhumidity;
|
|
}
|
|
return doc;
|
|
}
|
|
|
|
|
|
void logJson(JsonDocument jsondata) {
|
|
if(jsondata["model"].is<String>())
|
|
{
|
|
String ref = jsondata["model"];
|
|
if(jsondata["channel"].is<int>()) { ref = ref + jsondata["channel"].as<String>(); }
|
|
if(jsondata["id"].is<int>()) { ref = ref + jsondata["id"].as<String>(); }
|
|
if(!d1.contains(ref.c_str()) || millis() > (d1.get(ref.c_str()) + (MINDELAY * 1000)) || d1.get(ref.c_str()) > millis()) {
|
|
//Serial.println(ref.c_str());
|
|
//if(d1.contains(ref.c_str())) { Serial.println(d1.get(ref.c_str())); }
|
|
|
|
if(jsondata["model"].is<String>() && jsondata["model"] == "RadioHead-ASK") {
|
|
JsonArray payloadrh = jsondata["payload"];
|
|
bool treatrh = 0;
|
|
if(jsondata["len"].as<int>() == 7 && ((payloadrh[0].as<unsigned char>() & 0b00010000 ) > 0)) {
|
|
treatrh = true;
|
|
//Serial.println("Analyse RH Payload");
|
|
JsonDocument adoc = analyzeTH_type1(payloadrh);
|
|
jsondata["moisture"] = adoc["moisture"];
|
|
jsondata["battery_ok"] = adoc["battery_ok"];
|
|
jsondata["battery_V"] = adoc["battery_V"];
|
|
jsondata["battery_percent"] = adoc["battery_percent"];
|
|
jsondata["temperature_C"] = adoc["temperature_C"];
|
|
} else if(jsondata["len"].as<int>() == 5 && ((payloadrh[0].as<unsigned char>() & 0b00100000 ) > 0)) {
|
|
treatrh = true;
|
|
JsonDocument adoc = analyzeTH_type2(payloadrh);
|
|
jsondata["errcode"] = adoc["errcode"];
|
|
if(jsondata["errcode"] == 0) {
|
|
jsondata["temperature_C"] = adoc["temperature_C"];
|
|
jsondata["humidity"] = adoc["humidity"];
|
|
}
|
|
}
|
|
if(treatrh == true) {
|
|
jsondata.remove("from");
|
|
jsondata.remove("to");
|
|
jsondata.remove("payload");
|
|
jsondata.remove("len");
|
|
jsondata.remove("flags");
|
|
jsondata.remove("mic");
|
|
jsondata.remove("duration");
|
|
}
|
|
}
|
|
|
|
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
|
char JSONmessageBuffer[measureJson(jsondata) + 1];
|
|
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
|
|
#else
|
|
char JSONmessageBuffer[JSON_MSG_BUFFER];
|
|
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
|
|
#endif
|
|
d1.set(ref.c_str(), millis());
|
|
Serial.println(JSONmessageBuffer);
|
|
ledblink();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
void logJsonRH(JsonDocument jsondata) {
|
|
if(jsondata["model"].is<String>() && jsondata["model"] == "RadioHead-ASK") {
|
|
JsonArray payloadrh = jsondata["payload"];
|
|
bool treatrh = 0;
|
|
if(jsondata["len"].as<int>() == 6 && ((payloadrh[0].as<unsigned char>() & 0b00010000 ) > 0)) {
|
|
treatrh = true;
|
|
//Serial.println("Analyse RH Payload");
|
|
JsonDocument adoc = analyzeTH_type1(payloadrh);
|
|
jsondata["moisture"] = adoc["moisture"];
|
|
jsondata["battery_ok"] = adoc["battery_ok"];
|
|
jsondata["battery_V"] = adoc["battery_V"];
|
|
jsondata["battery_percent"] = adoc["battery_percent"];
|
|
jsondata["temperature_C"] = adoc["temperature_C"];
|
|
}
|
|
if(treatrh == true) {
|
|
jsondata.remove("from");
|
|
jsondata.remove("to");
|
|
jsondata.remove("payload");
|
|
jsondata.remove("len");
|
|
jsondata.remove("flags");
|
|
jsondata.remove("mic");
|
|
jsondata.remove("duration");
|
|
}
|
|
}
|
|
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
|
char JSONmessageBuffer[measureJson(jsondata) + 1];
|
|
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
|
|
#else
|
|
char JSONmessageBuffer[JSON_MSG_BUFFER];
|
|
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
|
|
#endif
|
|
Serial.println(JSONmessageBuffer);
|
|
//Serial.print(JSONmessageBuffer);
|
|
//Serial.println();
|
|
//ledblink();
|
|
}
|
|
*/
|
|
|
|
void logJsonAll(JsonDocument jsondata) {
|
|
// Serial.println(count);
|
|
#if defined(ESP8266) || defined(ESP32) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__)
|
|
char JSONmessageBuffer[measureJson(jsondata) + 1];
|
|
serializeJson(jsondata, JSONmessageBuffer, measureJson(jsondata) + 1);
|
|
#else
|
|
char JSONmessageBuffer[JSON_MSG_BUFFER];
|
|
serializeJson(jsondata, JSONmessageBuffer, JSON_MSG_BUFFER);
|
|
#endif
|
|
Serial.println(JSONmessageBuffer);
|
|
//ledblink();
|
|
}
|
|
|
|
|
|
void sendBME280() {
|
|
JsonDocument jsonDocument;
|
|
jsonDocument["model"]="LocalSensors";
|
|
jsonDocument["protocol"]="Local Sensors";
|
|
//jsonDocument["channel"]=1;
|
|
//jsonDocument["id"]=1;
|
|
float temp(NAN), hum(NAN), pres(NAN);
|
|
|
|
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
|
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
|
|
EnvironmentCalculations::AltitudeUnit envAltUnit = EnvironmentCalculations::AltitudeUnit_Meters;
|
|
EnvironmentCalculations::TempUnit envTempUnit = EnvironmentCalculations::TempUnit_Celsius;
|
|
|
|
bme.read(pres, temp, hum, tempUnit, presUnit);
|
|
|
|
if(!isnan(pres) && !isnan(temp) && !isnan(hum)) {
|
|
|
|
//float temp2 = (int)(temp * 100 + .5);
|
|
//jsonDocument["temperature_C"]=(float)temp2 / 100;
|
|
jsonDocument["temperature_C"]=temp;
|
|
jsonDocument["humidity"]=(int8_t) roundf(hum);
|
|
//jsonDocument["pressure"]=EnvironmentCalculations::EquivalentSeaLevelPressure(ALTITUDE, temp, pres, envAltUnit, envTempUnit);
|
|
//float pres2 = (int)(pres * 10 + .5);
|
|
//jsonDocument["pressure"]=(float)pres2 / 10;
|
|
jsonDocument["pressure"]=pres;
|
|
|
|
logJson(jsonDocument);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void ledblink() {
|
|
digitalWrite(LED, LOW);
|
|
delay(150);
|
|
digitalWrite(LED, HIGH);
|
|
}
|
|
|
|
void setup() {
|
|
//Serial.setTxBufferSize(512);
|
|
//Serial.setTxTimeoutMs(100);
|
|
Serial.begin(115200);
|
|
delay(10000);
|
|
//for (int i=0 ; i<10; i++) {
|
|
// Serial.print("Hello");
|
|
// delay(1000);
|
|
//}
|
|
/*Serial.print("MISO ");
|
|
Serial.println(MISO);
|
|
Serial.print("MOSI ");
|
|
Serial.println(MOSI);
|
|
Serial.print("SS ");
|
|
Serial.println(SS);
|
|
Serial.print("SCK ");
|
|
Serial.println(SCK);
|
|
*/
|
|
/*SPI.begin(SCK, MISO, MOSI, SS);
|
|
SPI.setFrequency(4000000);*/
|
|
SPI.setFrequency(4000000);
|
|
Serial.printf("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, CS=%d)\n", SCK, MISO, MOSI, SS);
|
|
Serial.print("RF_MODULE_RECEIVER_GPIO ");
|
|
Serial.println(RF_MODULE_RECEIVER_GPIO);
|
|
/* if(SS != 21 || MOSI != 20 || MISO != 10 || SCK != 7)
|
|
{
|
|
for ( ; ; ) {
|
|
Serial.println("Please define pin assignment for SPI in pins_arduino.h (~/.platformio/packages/framework-arduinoespressif32/variants/esp32c3) / SS: 21 MOSI : 20 MISO : 10 SCK : 7");
|
|
delay(1000);
|
|
}
|
|
} */
|
|
pinMode(LED, OUTPUT);
|
|
digitalWrite(LED, HIGH);
|
|
rf.initReceiver(RF_MODULE_RECEIVER_GPIO, RF_MODULE_FREQUENCY);
|
|
rf.setCallback(rtl_433_Callback, messageBuffer, JSON_MSG_BUFFER);
|
|
rf.enableReceiver();
|
|
rf.getModuleStatus();
|
|
|
|
//d = new Dictionary(25);
|
|
//d("aa", "bb");
|
|
//if(d1("aa")) { Serial.println("toto"); }
|
|
Wire.begin();
|
|
sensors_enabled = bme.begin();
|
|
|
|
}
|
|
|
|
void loop() {
|
|
rf.loop();
|
|
if(sensors_enabled == true && (millis() > (lastts_localsensors + (DELAYLOCALSENSORS*1000) + random(0, 5000)) || lastts_localsensors > millis())) {
|
|
lastts_localsensors = millis();
|
|
sendBME280();
|
|
}
|
|
/*if(kakucode > 0 && (millis() > (lastrcv + DELAYKAKUSEND) || lastrcv > millis())) {
|
|
rf.disableReceiver();
|
|
radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
|
|
radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
|
rf.enableReceiver();
|
|
kakucode = 0;
|
|
}*/
|
|
if (Serial.available())
|
|
{
|
|
// Read the JSON document from the "link" serial port
|
|
JsonDocument doc;
|
|
DeserializationError err = deserializeJson(doc, Serial);
|
|
|
|
if (err == DeserializationError::Ok)
|
|
{
|
|
Serial.print("cmd = ");
|
|
Serial.println(doc["cmd"].as<String>());
|
|
Serial.print("value = ");
|
|
Serial.println(doc["value"].as<uint32_t>());
|
|
if(doc["cmd"].as<String>().compareTo(String("rcsend"))==0) {
|
|
Serial.println("Transmit RCSwitch");
|
|
ledblink();
|
|
//rf.disableReceiver();
|
|
//radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
|
|
//mySwitch.enableTransmit(RF_MODULE_GDO0);
|
|
//mySwitch.enableTransmit(RCSWITCH_PIN);
|
|
//mySwitch.setRepeatTransmit(8);
|
|
//mySwitch.setRepeatTransmit(5);
|
|
//mySwitch.send(doc["value"].as<uint32_t>(), 24);
|
|
//mySwitch.disableTransmit();
|
|
//radiotx.SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
|
//rf.enableReceiver();
|
|
//rf.getModuleStatus();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Print error to the "debug" serial port
|
|
Serial.print("deserializeJson() returned ");
|
|
Serial.println(err.c_str());
|
|
|
|
// Flush all bytes in the "link" serial port buffer
|
|
while (Serial.available() > 0)
|
|
Serial.read();
|
|
}
|
|
}
|
|
}
|