Initial commit

This commit is contained in:
fauresystems
2019-11-03 09:34:43 +01:00
commit 3fe6e980c2
36 changed files with 3188 additions and 0 deletions
+191
View File
@@ -0,0 +1,191 @@
/*
Name: Props.cpp
Created: 29/10/2019 09:20:31
Author: Marie Faure <dev at faure dot systems>
Editor: https://github.com/fauresystems
License: MIT License (c) Marie Faure <dev at faure dot systems>
Base class to make props sketch for Escape Room 2.0 (connected).
*/
#include "Props.h"
#include <Process.h>
void PropsCallback::run(char* topic, byte* payload, unsigned int len)
{
if (len)
{
char* p = (char*)malloc(len + 1);
memcpy(p, payload, len);
p[len] = '\0';
if (String(p) == "@PING")
client->publish(outbox, "PONG");
else
Props::onInboxMessageReceived(p);
free(p);
}
}
void PropsMessageReceived::run(String a)
{
client->publish(outbox, String("OMIT " + a).c_str());
}
Props::Props(const char* client_id, const char* in_box, const char* out_box, const char* broker, const int port)
{
clientId = client_id;
inbox = in_box;
outbox = out_box;
_nextReconAttempt = 0;
_dataSentCount = 0;
_maximumSilentPeriod = 30; // 30 seconds
_payloadMax = MQTT_MAX_PACKET_SIZE - (1 + 2 + strlen(Props::outbox));
_brokerIpAddress.fromString(broker);
_client.setServer(_brokerIpAddress, port);
PropsCallback::client = &_client;
PropsCallback::outbox = outbox;
_client.setCallback(PropsCallback::run);
PropsMessageReceived::client = &_client;
PropsMessageReceived::outbox = outbox;
_sendDataAction.reset(400); // check data changes every 400 milliseconds
}
void Props::addData(PropsData* d)
{
_dataTable.push_back(d);
}
void Props::loop()
{
if (_client.connected())
{
_client.loop();
}
else if (millis() > _nextReconAttempt)
{
_nextReconAttempt += 5000L;
if (_client.connect(clientId, outbox, 2, true, "DISCONNECTED"))
{
_client.publish(outbox, "CONNECTED", true);
_client.subscribe(inbox, 1); // max QoS is 1 for PubSubClient subsciption
_nextReconAttempt = 0L;
}
}
if (_sendDataAction.tick()) checkDataChanges(); // send data changes if any
}
void Props::checkDataChanges()
{
if (_dataSentCount) {
sendDataChanges();
} else {
sendAllData();
}
++_dataSentCount;
// don't be silent to long
if (_dataSentCount > (_maximumSilentPeriod * 1000 / _sendDataAction.getInterval())) _dataSentCount = 0;
}
void Props::sendAllData()
{
String data("DATA "), str;
for (SimpleList<PropsData*>::iterator itr = _dataTable.begin(); itr != _dataTable.end(); ++itr) {
str = (*itr)->fetch();
send(&data, &str);
}
if (data.length() > 5) {
_client.publish(outbox, data.c_str());
}
}
void Props::sendDataChanges()
{
String data("DATA "), str;
for (SimpleList<PropsData*>::iterator itr = _dataTable.begin(); itr != _dataTable.end(); ++itr) {
str = (*itr)->fetchChange();
send(&data, &str);
}
if (data.length() > 5) {
_client.publish(outbox, data.c_str());
}
}
void Props::send(String* d, String* s)
{
if (d->length() + s->length() <= _payloadMax) {
*d += *s;
} else if (s->length() > _payloadMax + 5) {
sendMesg(u8"Data ignored, loo larged to be sent");
} else if (d->length() + s->length() > _payloadMax) {
_client.publish(outbox, d->c_str());
*d = "DATA " + *s;
}
}
void Props::sendData(String data) {
if (data.length() > 5) {
_client.publish(outbox, String("DATA " + data).c_str());
}
}
void Props::sendDone(String action) {
_client.publish(outbox, String("DONE " + action).c_str());
}
void Props::sendMesg(String mesg) {
if (mesg.length() > 5) {
_client.publish(outbox, String("MESG " + mesg).c_str());
}
}
void Props::sendMesg(String mesg, char *topic) {
if (mesg.length() > 5) {
_client.publish(topic, String("MESG " + mesg).c_str());
}
}
void Props::sendOmit(String action) {
_client.publish(outbox, String("OMIT " + action).c_str());
}
void Props::sendOver(String challenge) {
_client.publish(outbox, String("OMIT " + challenge).c_str());
}
void Props::sendProg(String program) {
_client.publish(outbox, String("PROGRAM " + program).c_str());
}
void Props::sendRequ(String request) {
_client.publish(outbox, String("REQU " + request).c_str());
}
void Props::sendRequ(String action, char* topic) {
_client.publish(topic, String("OMIT " + action).c_str());
}
void Props::resetIntervals(const int changes, const int silent)
{
_nextReconAttempt = 0;
_dataSentCount = 0;
_maximumSilentPeriod = silent; // seconds
_sendDataAction.reset(changes); // milliseconds
}
PubSubClient *PropsCallback::client;
const char *PropsCallback::outbox;
PubSubClient *PropsMessageReceived::client;
const char *PropsMessageReceived::outbox;
void (*Props::onInboxMessageReceived)(String) = PropsMessageReceived::run;