refactor: split logic for incoming and outgoing json #3

Merged
nicu merged 6 commits from gw/optmisation into gateway 2022-10-27 11:05:38 +02:00
6 changed files with 197 additions and 135 deletions

View File

@ -1,5 +1,6 @@
#if DHT_SENSOR
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHT11_PIN 12
@ -9,27 +10,30 @@ DHT dht = DHT(DHT11_PIN, DHT11);
unsigned long currentTime = 0;
namespace Dht {
void setup() {
void setup() {
dht.begin();
}
}
void read(JsonDocument& jsonDoc) {
void read() {
currentTime = millis();
static unsigned long lastReadTime = 0;
if (currentTime > lastReadTime) {
lastReadTime = currentTime + READ_INTERVAL(5);
StaticJsonDocument<200> jsonDoc;
JsonObject dht11 = jsonDoc.createNestedObject("dht11");
dht11["temperature"] = dht.readTemperature();
dht11["humidity"] = dht.readHumidity();
serializeJson(jsonDoc, Serial);
Serial.println();
}
}
}
#else
namespace Dht {
void setup() {
}
void read(JsonDocument& jsonDoc) {
void setup() {
}
void read() {
}
}
#endif

View File

@ -0,0 +1,26 @@
#pragma once
#include <ArduinoJson.h>
#include <RCSwitch.h>
class Protocol {
protected:
unsigned int protocol;
public:
Protocol(unsigned int protocol) {
this->protocol = protocol;
}
virtual void fromJson(JsonObjectConst& rcSwitch, RCSwitch& rcDevice) {
unsigned int protocol = rcSwitch["protocol"];
rcDevice.setProtocol(protocol);
rcDevice.send(rcSwitch["value"]);
}
virtual void toJson(unsigned long value, JsonDocument& jsonDoc) {
JsonObject rcSwitch = jsonDoc.createNestedObject("rcSwitch");
rcSwitch["protocol"] = protocol;
rcSwitch["value"] = value;
}
};

View File

@ -0,0 +1,68 @@
#pragma once
#include "Protocol.h"
#define RC_STATE(value) value & 0x1
#define RC_DEVICE(value) (value >> 1) & 0x1F
#define RC_GROUP(value) (value >> 6) & 0x1F
class Protocol_1 : public Protocol {
public:
Protocol_1() : Protocol(1) {
}
void fromJson(JsonObjectConst& rcSwitch, RCSwitch& rcDevice) override {
unsigned int protocol = rcSwitch["protocol"];
rcDevice.setProtocol(protocol);
char* group = rcSwitch["group"];
int channel = rcSwitch["channel"];
rcSwitch["state"] ? rcDevice.switchOn(group, channel) : rcDevice.switchOff(group, channel);
}
void toJson(unsigned long value, JsonDocument& jsonDoc) override {
JsonObject rcSwitch = jsonDoc.createNestedObject("rcSwitch");
rcSwitch["protocol"] = protocol;
Decoder decoder;
decoder.decode(value);
rcSwitch["state"] = decoder.state;
rcSwitch["group"] = String(decoder.group, BIN);
rcSwitch["channel"] = decoder.device;
}
private:
struct Decoder {
bool state;
char group;
byte device;
void decode(unsigned long value) {
value = value >> 2;
unsigned long res = 0;
for (int i = 0; i < 12; i++) {
res |= ((value & 1) ^ 1) << i;
value = value >> 2;
}
state = RC_STATE(res);
group = RC_GROUP(res);
switch (RC_DEVICE(res)) {
case 0b10000:
device = 1;
break;
case 0b01000:
device = 2;
break;
case 0b00100:
device = 3;
break;
case 0b00010:
device = 4;
break;
case 0b00001:
device = 5;
break;
}
}
};
} protocol_1;

View File

@ -0,0 +1,67 @@
#pragma once
#include "Protocol.h"
#include "Tiny.h"
class Protocol_2 : public Protocol {
public:
Protocol_2() : Protocol(2) {
}
void toJson(unsigned long value, JsonDocument& jsonDoc) override {
switch (value) {
case 637541753L:
case 771759481L: {
JsonObject motion = jsonDoc.createNestedObject("motion");
motion["kitchen"] = value == 637541753L ? "on" : "off";
break;
}
case 1879048230L:
case 1879048198L: {
JsonObject motion = jsonDoc.createNestedObject("motion");
motion["basement"] = value == 1879048230L ? "on" : "off";
break;
}
default:
StaticJsonDocument<200> jsonSensor;
if (buildSensorJson(value, jsonSensor)) {
jsonDoc.add(jsonSensor);
} else {
Protocol::toJson(value, jsonDoc);
}
break;
}
}
private:
bool buildSensorJson(unsigned long value, JsonDocument& jsonDoc) {
JsonObject sensor = jsonDoc.createNestedObject("sensor");
sensor["id"] = ID(value);
float voltage = (float)GET_VCC(value) / 1000;
if (voltage != 0) {
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
diagnostic["voltage"] = voltage;
}
switch (GET_TYPE(value)) {
case SensorType::GENERIC:
sensor["value"] = GET_VALUE(value);
break;
case SensorType::TEMPERATURE:
sensor["temperature"] = (float)GET_TEMP(value) / 10;
break;
case SensorType::HUMIDITY:
sensor["humidity"] = (float)GET_HUMIDITY(value) / 10;
break;
case SensorType::CONTACT:
sensor["state"] = GET_STATE(value) ? "on" : "off";
break;
default:
return false;
}
return true;
}
} protocol_2;

View File

@ -1,40 +0,0 @@
#define RC_STATE(value) value & 0x1
#define RC_DEVICE(value) (value >> 1) & 0x1F
#define RC_GROUP(value) (value >> 6) & 0x1F
namespace RcDecoder {
struct RcSwitch {
bool state;
char group;
byte device;
};
void decode(unsigned long value, RcSwitch& decoded) {
value = value >> 2;
unsigned long res = 0;
for (int i = 0; i < 12; i++) {
res |= ((value & 1) ^ 1) << i;
value = value >> 2;
}
decoded.state = RC_STATE(res);
decoded.group = RC_GROUP(res);
switch (RC_DEVICE(res)) {
case 0b10000:
decoded.device = 1;
break;
case 0b01000:
decoded.device = 2;
break;
case 0b00100:
decoded.device = 3;
break;
case 0b00010:
decoded.device = 4;
break;
case 0b00001:
decoded.device = 5;
break;
}
}
}

View File

@ -1,10 +1,8 @@
#include <Arduino.h>
#include <RCSwitch.h>
#include <Adafruit_Sensor.h>
#include "Tiny.h"
#include <ArduinoJson.h>
#include "Dht.h"
#include "RcDecoder.h"
#include "Protocol_1.h"
#include "Protocol_2.h"
#define RESET_PIN 10
#define SEND_PIN 11
@ -13,9 +11,6 @@
RCSwitch mySwitch = RCSwitch();
void readRcSwitch(JsonDocument& jsonDoc);
void readCommand();
void setup() {
digitalWrite(RESET_PIN, HIGH);
pinMode(LED_BUILTIN, OUTPUT);
@ -32,77 +27,27 @@ void setup() {
delay(1000);
}
void loop() {
readCommand();
StaticJsonDocument<200> jsonDoc;
readRcSwitch(jsonDoc);
Dht::read(jsonDoc);
if (!jsonDoc.isNull()) {
serializeJson(jsonDoc, Serial);
Serial.println();
}
}
bool buildSensorJson(JsonDocument& jsonDoc, unsigned long value) {
JsonObject sensor = jsonDoc.createNestedObject("sensor");
sensor["id"] = ID(value);
float voltage = (float)GET_VCC(value) / 1000;
if (voltage != 0) {
JsonObject diagnostic = sensor.createNestedObject("diagnostic");
diagnostic["voltage"] = voltage;
}
switch (GET_TYPE(value)) {
case SensorType::GENERIC:
sensor["value"] = GET_VALUE(value);
break;
case SensorType::TEMPERATURE:
sensor["temperature"] = (float)GET_TEMP(value) / 10;
break;
case SensorType::HUMIDITY:
sensor["humidity"] = (float)GET_HUMIDITY(value) / 10;
break;
case SensorType::CONTACT:
sensor["state"] = GET_STATE(value) ? "on" : "off";
break;
Protocol findProtocol(unsigned int protocol) {
switch (mySwitch.getReceivedProtocol()) {
case 1:
return protocol_1;
case 2:
return protocol_2;
default:
return false;
return Protocol(protocol);
}
return true;
}
void readRcSwitch(JsonDocument& jsonDoc) {
void readRcSwitch() {
if (mySwitch.available()) {
unsigned long value = mySwitch.getReceivedValue();
mySwitch.resetAvailable();
if (mySwitch.getReceivedProtocol() == 2) {
if (value == 637541753L || value == 771759481L) {
JsonObject motion = jsonDoc.createNestedObject("motion");
motion["kitchen"] = value == 637541753L ? "on" : "off";
return;
}
if (value == 1879048230L || value == 1879048198L) {
JsonObject motion = jsonDoc.createNestedObject("motion");
motion["basement"] = value == 1879048230L ? "on" : "off";
return;
}
if (buildSensorJson(jsonDoc, value)) {
return;
}
}
JsonObject rcSwitch = jsonDoc.createNestedObject("rcSwitch");
rcSwitch["protocol"] = mySwitch.getReceivedProtocol();
if (mySwitch.getReceivedProtocol() == 1) {
RcDecoder::RcSwitch decoded;
RcDecoder::decode(value, decoded);
rcSwitch["state"] = decoded.state;
rcSwitch["group"] = String(decoded.group, BIN);
rcSwitch["channel"] = decoded.device;
} else {
rcSwitch["value"] = value;
StaticJsonDocument<200> jsonDoc;
findProtocol(mySwitch.getReceivedProtocol()).toJson(value, jsonDoc);
if (!jsonDoc.isNull()) {
serializeJson(jsonDoc, Serial);
Serial.println();
}
}
}
@ -113,23 +58,6 @@ void blink() {
digitalWrite(LED_BUILTIN, LOW);
}
void runRcSwitchCommand(JsonVariant jsonDoc) {
JsonObject rcSwitch = jsonDoc["rcSwitch"];
unsigned int protocol = rcSwitch["protocol"];
if (protocol == 1) {
mySwitch.setProtocol(protocol);
char* group = rcSwitch["group"];
int channel = rcSwitch["channel"];
rcSwitch["state"] ? mySwitch.switchOn(group, channel) : mySwitch.switchOff(group, channel);
} else {
mySwitch.setProtocol(protocol);
mySwitch.send(rcSwitch["value"]);
}
serializeJson(jsonDoc, Serial);
Serial.println();
// blink();
}
void runJsonCommands(const char* cmd) {
String origCmd = String(cmd);
StaticJsonDocument<512> jsonArray;
@ -138,7 +66,10 @@ void runJsonCommands(const char* cmd) {
JsonArray array = jsonArray.as<JsonArray>();
for (JsonVariant jsonDoc : array) {
if (jsonDoc.containsKey("rcSwitch")) {
runRcSwitchCommand(jsonDoc);
JsonObjectConst rcSwitch = jsonDoc["rcSwitch"];
findProtocol(rcSwitch["protocol"]).fromJson(rcSwitch, mySwitch);
serializeJson(jsonDoc, Serial);
Serial.println();
}
}
} else {
@ -164,3 +95,9 @@ void readCommand() {
runJsonCommands(cmd.c_str());
}
}
void loop() {
readCommand();
readRcSwitch();
Dht::read();
}