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
+11
View File
@@ -0,0 +1,11 @@
/*
Name: ArduinoProps.h
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>
Library to make props sketch for Escape Room 2.0 (connected props).
*/
#include "ArduinoProps.h"
+26
View File
@@ -0,0 +1,26 @@
/*
Name: ArduinoProps.h
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>
Library to make props sketch for Escape Room 2.0 (connected props).
*/
#ifndef _ArduinoProps_h
#define _ArduinoProps_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
#include "BridgeProps.h"
#include "EthernetProps.h"
#include "WifiProps.h"
#include "PropsAction.h"
#include "PropsData.h"
#endif
+28
View File
@@ -0,0 +1,28 @@
/*
Name: BridgeProps.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>
Class Props for Arduino Yun and Dragino Yun shield.
*/
#include "BridgeProps.h"
BridgeProps::BridgeProps(const char* client_id, const char* in_box, const char* out_box, const char* broker, const int port)
: Props(client_id, in_box, out_box, broker, port)
{
_client.setClient(_bridgeClient);
}
void BridgeProps::begin(void(*on_message)(String))
{
if (on_message) onInboxMessageReceived = on_message;
}
void BridgeProps::setBrokerIpAddress(IPAddress ip)
{
_brokerIpAddress = ip;
}
+28
View File
@@ -0,0 +1,28 @@
/*
Name: BridgeProps.h
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>
Class Props for Arduino Yun and Dragino Yun shield.
*/
#ifndef BRIDGEPROPS_H
#define BRIDGEPROPS_H
#include <BridgeClient.h>
#include <IPAddress.h>
#include "Props.h"
class BridgeProps : public Props
{
public:
BridgeProps(const char*, const char*, const char*, const char*, const int);
void begin(void(*)(String) = NULL);
void setBrokerIpAddress(IPAddress);
private:
BridgeClient _bridgeClient;
};
#endif
+22
View File
@@ -0,0 +1,22 @@
/*
Name: EthernetProps.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>
Class Props for Arduino with Ethernet shield.
*/
#include "EthernetProps.h"
EthernetProps::EthernetProps(const char* client_id, const char* in_box, const char* out_box, const char* broker, const int port)
: Props(client_id, in_box, out_box, broker, port)
{
_client.setClient(_ethernetClient);
}
void EthernetProps::begin(void(*on_message)(String))
{
if (on_message) onInboxMessageReceived = on_message;
}
+29
View File
@@ -0,0 +1,29 @@
/*
Name: EthernetProps.h
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>
Class Props for Arduino with Ethernet shield.
*/
#ifndef ETHERNETPROPS_H
#define ETHERNETPROPS_H
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include "Props.h"
class EthernetProps : public Props
{
public:
EthernetProps(const char*, const char*, const char*, const char*, const int);
void begin(void(*)(String) = NULL);
private:
EthernetClient _ethernetClient;
};
#endif
+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;
+92
View File
@@ -0,0 +1,92 @@
/*
Name: Props.h
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).
*/
#ifndef PROPS_H
#define PROPS_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
#include <BridgeClient.h>
#include <PubSubClient.h>
#include <SimpleList.h>
#include "PropsAction.h"
#include "PropsData.h"
#ifndef MQTT_MAX_PACKET_SIZE
#define MQTT_MAX_PACKET_SIZE 128 // Bridge tranfer stuff (see PubSubClient)
#endif
class PropsCallback
{
public:
static PubSubClient *client;
static const char *outbox;
static void run(char* topic, byte* payload, unsigned int len);
};
class PropsMessageReceived
{
public:
static PubSubClient *client;
static const char *outbox;
static void run(String);
};
class InboxMessage : public PropsMessageReceived
{
public:
static void run(String); // to be implemented in .ino sketch
};
class Props
{
public:
Props(const char*, const char*, const char*, const char*, const int=1883);
virtual void begin(void(*)(String) = NULL) = 0;
void addData(PropsData*);
void loop();
void resetIntervals(const int changes, const int silent);
void sendAllData();
void sendDataChanges();
void sendData(String); // only in outbox
void sendDone(String);
void sendMesg(String);
void sendMesg(String, char*);
void sendOmit(String);
void sendOver(String);
void sendProg(String);
void sendRequ(String);
void sendRequ(String, char*);
static void (*onInboxMessageReceived)(String);
const char *clientId;
const char *inbox;
const char *outbox;
protected:
void checkDataChanges();
void send(String*, String*);
IPAddress _brokerIpAddress;
PubSubClient _client;
uint16_t _dataSentCount;
uint8_t _maximumSilentPeriod;
unsigned long _nextReconAttempt;
uint8_t _payloadMax;
PropsAction _sendDataAction;
SimpleList<PropsData*> _dataTable;
};
#endif
+66
View File
@@ -0,0 +1,66 @@
/*
Name: PropsAction.h
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>
Provide an easy way of triggering functions at a set _interval.
*/
#include "PropsAction.h"
PropsAction::PropsAction()
{
_active = true;
_previous = 0;
_interval = 400;
_execute = NULL;
}
PropsAction::PropsAction(unsigned long intervl, void (*function)())
{
_active = true;
_previous = 0;
_interval = intervl;
_execute = function;
}
void PropsAction::reset(unsigned long intervl)
{
_active = true;
_previous = 0;
_interval = intervl;
}
void PropsAction::disable()
{
_active = false;
}
void PropsAction::enable()
{
_active = true;
}
void PropsAction::check() {
if (_active && (millis() - _previous >= _interval))
{
_previous = millis();
if (_execute) _execute();
}
}
bool PropsAction::tick() {
if (_active && (millis() - _previous >= _interval))
{
_previous = millis();
return true;
}
return false;
}
unsigned long PropsAction::getInterval()
{
return _interval;
}
+43
View File
@@ -0,0 +1,43 @@
/*
Name: PropsAction.h
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>
Provide an easy way of triggering functions at a set interval.
*/
#ifndef PROPSACTION_H
#define PROPSACTION_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
class Props;
class PropsAction {
public:
PropsAction();
PropsAction(unsigned long interval, void (*function)());
void reset(unsigned long interval);
void disable();
void enable();
void check();
bool tick();
unsigned long getInterval();
private:
bool _active;
unsigned long _previous;
unsigned long _interval;
void (*_execute)();
};
#endif
+136
View File
@@ -0,0 +1,136 @@
/*
Name: PropsData.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>
Variable wrapper for connected props.
*/
#include "PropsData.h"
#include <String.h>
// ---- Decimal
PropsDataDecimal::PropsDataDecimal(const char * id, uint8_t digits, double precision, double initial) {
_id = id;
_current = initial;
_previous = _current;
_precision = precision;
_digits = digits;
}
String PropsDataDecimal::fetch() {
_previous = _current;
return String(_id) + "=" + String(_current, _digits) + " ";
}
String PropsDataDecimal::fetchChange() {
if (_current != _previous && _current && abs(_current - _previous) / _current >= _precision) {
return fetch();
}
else if (_current != _previous && !_current && abs(_current - _previous) >= _precision) {
return fetch();
}
return String();
}
void PropsDataDecimal::setValue(const double v) {
_current = v;
}
double PropsDataDecimal::value() const {
return _current;
}
// ---- Integer
PropsDataInteger::PropsDataInteger(const char * id, double precision, long initial) {
_id = id;
_current = initial;
_previous = _current;
_precision = precision;
}
String PropsDataInteger::fetch() {
_previous = _current;
return String(_id) + "=" + String(_current) + " ";
}
String PropsDataInteger::fetchChange() {
if (_current != _previous && _current && abs(_current - _previous) / _current >= _precision) {
return fetch();
}
else if (_current != _previous && !_current && abs(_current - _previous) >= _precision) {
return fetch();
}
return String();
}
void PropsDataInteger::setValue(const long v) {
_current = v;
}
long PropsDataInteger::value() const {
return _current;
}
// ---- Logical
PropsDataLogical::PropsDataLogical(const char * id, const char *trueval, const char *falseval, bool initial) {
_id = id;
_current = initial;
_previous = _current;
_trueString = trueval;
_falseString = falseval;
}
String PropsDataLogical::fetch() {
String str(String(_id) + "=");
if (_current) {
str += _trueString ? _trueString : "1";
} else {
str += _falseString ? _falseString : "0";
}
str += " ";
_previous = _current;
return str;
}
String PropsDataLogical::fetchChange() {
if (_current != _previous) {
return fetch();
}
return String();
}
void PropsDataLogical::setValue(const bool v) {
_current = v;
}
bool PropsDataLogical::value() const {
return _current;
}
// ---- Text
PropsDataText::PropsDataText(const char * id) {
_id = id;
}
String PropsDataText::fetch() {
_previous = _current;
return String(_id) + "=" + _current + " ";
}
String PropsDataText::fetchChange() {
if (_current != _previous) {
return fetch();
}
return String();
}
void PropsDataText::setValue(String v) {
_current = v;
}
String PropsDataText::value() const {
return _current;
}
+90
View File
@@ -0,0 +1,90 @@
/*
Name: PropsData.h
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>
Variable wrapper for connected props.
*/
#ifndef PROPSDATA_H
#define PROPSDATA_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "arduino.h"
#else
#include "WProgram.h"
#endif
#include <inttypes.h>
#include <WString.h>
class PropsData
{
public:
virtual String fetch() = 0;
virtual String fetchChange() = 0;
};
class PropsDataDecimal : public PropsData
{
public:
PropsDataDecimal(const char *, uint8_t digits = 2, double precision = 0.1, double initial = 0);
String fetch();
String fetchChange();
void setValue(const double);
double value() const;
private:
const char *_id;
double _current;
double _previous;
double _precision;
uint8_t _digits;
};
class PropsDataInteger : public PropsData
{
public:
PropsDataInteger(const char *, double precision = 0.1, long initial = 0);
String fetch();
String fetchChange();
void setValue(const long);
long value() const;
private:
const char *_id;
long _current;
long _previous;
double _precision;
};
class PropsDataLogical : public PropsData
{
public:
PropsDataLogical(const char *, const char *trueval = NULL, const char *falseval = NULL, bool initial = false);
String fetch();
String fetchChange();
void setValue(const bool);
bool value() const;
private:
const char *_id;
bool _current;
bool _previous;
const char *_trueString;
const char *_falseString;
};
class PropsDataText : public PropsData
{
public:
PropsDataText(const char *);
String fetch();
String fetchChange();
void setValue(String);
String value() const;
private:
const char *_id;
String _current;
String _previous;
};
#endif
+29
View File
@@ -0,0 +1,29 @@
/*
Name: WifiProps.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>
Class Props for Arduino with Wifi shield.
*/
#include "WifiProps.h"
#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRVIDOR4000)
WifiProps::WifiProps(const char* client_id, const char* in_box, const char* out_box, const char* broker, const int port)
: Props(client_id, in_box, out_box, broker, port)
{
_client.setClient(_wifiClient);
}
void WifiProps::begin(void(*on_message)(String))
{
if (on_message) onInboxMessageReceived = on_message;
}
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
Name: WifiProps.h
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>
Class Props for Arduino with Wifi shield.
*/
#ifndef WIFIPROPS_H
#define WIFIPROPS_H
#if defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRVIDOR4000)
#include <WiFiNINA.h>
#include <SPI.h>
#include <WiFiClient.h>
#include "Props.h"
class WifiProps : public Props
{
public:
WifiProps(const char*, const char*, const char*, const char*, const int);
void begin(void(*)(String) = NULL);
private:
WiFiClient _wifiClient;
};
#endif
#endif