rf433gateway/src/main.ino

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