mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 12:17:05 +00:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f1dd6f6b8 | ||
|
|
8f7fd936b8 | ||
|
|
884205feea | ||
|
|
21bd7d73d1 | ||
|
|
cd60d32966 | ||
|
|
e53a92cd82 | ||
|
|
c618d37f0b | ||
|
|
f450aa4a01 | ||
|
|
32b9f40d02 | ||
|
|
ae082fd2bb | ||
|
|
315adbc42f | ||
|
|
face8a8bfc | ||
|
|
fe1025e470 | ||
|
|
4f6d7d1b82 | ||
|
|
894a01a534 | ||
|
|
a3317bcde1 | ||
|
|
6d9cbb3988 | ||
|
|
aa9cf0a795 | ||
|
|
d8244e1726 | ||
|
|
cabcd33a63 | ||
|
|
3140833abb | ||
|
|
890351b920 | ||
|
|
0868b983d4 | ||
|
|
997e612c97 | ||
|
|
aadb6e0521 | ||
|
|
fcd5c1ec01 | ||
|
|
e9c55e8685 | ||
|
|
72c57aa2e3 |
+1
-4
@@ -1,4 +1 @@
|
||||
.pioenvs
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.piolibdeps
|
||||
Version.h
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
[submodule "lib/Adafruit_NeoPixel"]
|
||||
path = lib/Adafruit_NeoPixel
|
||||
url = https://github.com/adafruit/Adafruit_NeoPixel.git
|
||||
[submodule "lib/ArduinoJson"]
|
||||
path = lib/ArduinoJson
|
||||
url = https://github.com/bblanchon/ArduinoJson.git
|
||||
[submodule "lib/IRremoteESP8266"]
|
||||
path = lib/IRremoteESP8266
|
||||
url = https://github.com/sebastienwarin/IRremoteESP8266.git
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
language: python
|
||||
python:
|
||||
- '2.7'
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "./.pioenvs"
|
||||
install:
|
||||
- pip install -U platformio
|
||||
script:
|
||||
- platformio run
|
||||
|
||||
before_deploy:
|
||||
- ./before_deploy
|
||||
- export RELEASE_FILE=$(ls ESPEasy*.zip)
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
prerelease: true
|
||||
api_key:
|
||||
secure: bZeuKI7evXeZYmGayfcvIC1fThBGcksAyOrCbZ8kAGeTbHGJqFLBBy8to5UpNBSZVfeDWo25Iqy8Pfbyb7p2c1hg6fG9jS0UzQkLnoUNMxpUM1dJACkZxvFdP4Br3Y3vUPWtrWUbo8rN/b3E6tjSNLE7vQiwsarj+eWTO2V6BGcsN0eHc04/UCM2+DcHvJ4y7Ec36yIUaClNAWMal1osBYaViruylOdBKT/WDs1ZMoJMceXCfxMQ/8J2moYvymKfSkXSmoMGmzlTuq8v5N4AweutjpC4Zba2BbxIJv+PwWjhfIgTviHFggSU90UPTKVWYv13vms92VVKz1CDVrUQNn+YQes9+ROPUnrMc9bJ+q7E1lWJRZeDMqGECB+8BjUtUk6H81K+XhOnW1mtZiMnvMCwkmE0OT1eBObGMcpR962/DUBoQDmulMs2IieB0dLobmUBhpc1syrKEPKxjY7yhhQMr6In82jODVLR3qDkNQ8xtIfevzCo/ocUjiOrXW4b/pDMy28Yh109DMb/KSWEsjjkkpXhsT1YVy2MwOa7FRhHFW+SNKX4Us8T75H+pO4mQ4afnPEtjYKodj7XD92zqNxKfMx3elEx5RK6HKekHjpXdYtuXzGONB9StA+2T43/2llt3n5fzv4BRfCumBEJ77/ufB0U/uhsCe6lVwJf34U=
|
||||
file_glob: true
|
||||
file: "${RELEASE_FILE}"
|
||||
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
# repo: psy0rz/ESPEasy-platformio
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
+65
-140
@@ -1,5 +1,3 @@
|
||||
char* ramtest;
|
||||
|
||||
#define INPUT_COMMAND_SIZE 80
|
||||
void ExecuteCommand(byte source, const char *Line)
|
||||
{
|
||||
@@ -21,109 +19,6 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
// ****************************************
|
||||
// commands for debugging
|
||||
// ****************************************
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("background")) == 0)
|
||||
{
|
||||
success = true;
|
||||
unsigned long timer = millis() + Par1;
|
||||
Serial.println("start");
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
Serial.println("end");
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("executeRules")) == 0)
|
||||
{
|
||||
success = true;
|
||||
if (GetArgv(Line, TmpStr1, 2))
|
||||
{
|
||||
String fileName = TmpStr1;
|
||||
String event = "";
|
||||
rulesProcessingFile(fileName, event);
|
||||
}
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("clearRTCRAM")) == 0)
|
||||
{
|
||||
success = true;
|
||||
RTC.factoryResetCounter = 0;
|
||||
RTC.deepSleepState = 0;
|
||||
RTC.rebootCounter = 0;
|
||||
RTC.flashDayCounter = 0;
|
||||
RTC.flashCounter = 0;
|
||||
saveToRTC();
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("notify")) == 0)
|
||||
{
|
||||
success = true;
|
||||
String message = "";
|
||||
if (GetArgv(Line, TmpStr1, 3))
|
||||
message = TmpStr1;
|
||||
|
||||
if (Par1 > 0)
|
||||
{
|
||||
if (Settings.NotificationEnabled[Par1 - 1] && Settings.Notification[Par1 - 1] != 0)
|
||||
{
|
||||
byte NotificationProtocolIndex = getNotificationIndex(Settings.Notification[Par1 - 1]);
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.NotificationProtocolIndex = Par1 - 1;
|
||||
if (NPlugin_id[NotificationProtocolIndex] != 0)
|
||||
NPlugin_ptr[NotificationProtocolIndex](NPLUGIN_NOTIFY, &TempEvent, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("resetFlashWriteCounter")) == 0)
|
||||
{
|
||||
success = true;
|
||||
RTC.flashDayCounter = 0;
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("udptest")) == 0)
|
||||
{
|
||||
success = true;
|
||||
for (byte x = 0; x < Par2; x++)
|
||||
{
|
||||
String event = "Test ";
|
||||
event += x;
|
||||
SendUDPCommand(Par1, (char*)event.c_str(), event.length());
|
||||
}
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("sdcard")) == 0)
|
||||
{
|
||||
success = true;
|
||||
File root = SD.open("/");
|
||||
root.rewindDirectory();
|
||||
printDirectory(root, 0);
|
||||
root.close();
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("sdremove")) == 0)
|
||||
{
|
||||
success = true;
|
||||
String fname = Line;
|
||||
fname = fname.substring(9);
|
||||
Serial.print(F("Removing:"));
|
||||
Serial.println(fname.c_str());
|
||||
SD.remove((char*)fname.c_str());
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("lowmem")) == 0)
|
||||
{
|
||||
Serial.print(lowestRAM);
|
||||
Serial.print(F(" : "));
|
||||
Serial.println(lowestRAMid);
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("malloc")) == 0)
|
||||
{
|
||||
ramtest = (char *)malloc(Par1);
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("sysload")) == 0)
|
||||
{
|
||||
success = true;
|
||||
@@ -150,8 +45,6 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
Serial.println(sizeof(Settings));
|
||||
Serial.print(F("ExtraTaskSettingsStruct: "));
|
||||
Serial.println(sizeof(ExtraTaskSettings));
|
||||
Serial.print(F("DeviceStruct: "));
|
||||
Serial.println(sizeof(Device));
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("TaskClear")) == 0)
|
||||
@@ -203,13 +96,6 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
// commands for rules
|
||||
// ****************************************
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("deepSleep")) == 0)
|
||||
{
|
||||
success = true;
|
||||
if (Par1 > 0)
|
||||
deepSleep(Par1);
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("TaskValueSet")) == 0)
|
||||
{
|
||||
success = true;
|
||||
@@ -322,7 +208,7 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
addLog(LOG_LEVEL_DEBUG, line);
|
||||
delay(1);
|
||||
}
|
||||
@@ -331,6 +217,38 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
// ****************************************
|
||||
// special commands for Blynk
|
||||
// ****************************************
|
||||
|
||||
if (strcasecmp(Command, "BlynkGet") == 0)
|
||||
{
|
||||
String event = Line;
|
||||
event = event.substring(9);
|
||||
int index = event.indexOf(',');
|
||||
if (index > 0)
|
||||
{
|
||||
int index = event.lastIndexOf(',');
|
||||
String blynkcommand = event.substring(index+1);
|
||||
float value = 0;
|
||||
if (Blynk_get(blynkcommand, &value))
|
||||
{
|
||||
UserVar[(VARS_PER_TASK * (Par1 - 1)) + Par2 - 1] = value;
|
||||
}
|
||||
else
|
||||
status = F("Error getting data");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Blynk_get(event))
|
||||
{
|
||||
status = F("Error getting data");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// ****************************************
|
||||
// configure settings commands
|
||||
@@ -356,7 +274,7 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
if (strcasecmp_P(Command, PSTR("WifiConnect")) == 0)
|
||||
{
|
||||
success = true;
|
||||
WifiConnect(true, 1);
|
||||
WifiConnect(1);
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("WifiDisconnect")) == 0)
|
||||
@@ -382,6 +300,9 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
if (strcasecmp_P(Command, PSTR("Erase")) == 0)
|
||||
{
|
||||
success = true;
|
||||
EraseFlash();
|
||||
ZeroFillFlash();
|
||||
saveToRTC(0);
|
||||
WiFi.persistent(true); // use SDK storage of SSID/WPA parameters
|
||||
WiFi.disconnect(); // this will store empty ssid/wpa into sdk storage
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
@@ -405,6 +326,34 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("FlashDump")) == 0)
|
||||
{
|
||||
success = true;
|
||||
uint32_t _sectorStart = ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t _sectorEnd = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
|
||||
Serial.print(F("Sketch size : "));
|
||||
Serial.println(ESP.getSketchSize());
|
||||
Serial.print(F("Sketch free space : "));
|
||||
Serial.println(ESP.getFreeSketchSpace());
|
||||
Serial.print(F("Flash size : "));
|
||||
Serial.println(ESP.getFlashChipRealSize());
|
||||
Serial.print(F("SPIFFS start sector: "));
|
||||
Serial.println(_sectorStart);
|
||||
Serial.print(F("SPIFFS end sector : "));
|
||||
Serial.println(_sectorEnd);
|
||||
char data[80];
|
||||
if (Par2 == 0) Par2 = Par1;
|
||||
for (int x = Par1; x <= Par2; x++)
|
||||
{
|
||||
LoadFromFlash(x * 1024, (byte*)&data, sizeof(data));
|
||||
Serial.print(F("Offset: "));
|
||||
Serial.print(x);
|
||||
Serial.print(" : ");
|
||||
Serial.println(data);
|
||||
}
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("Debug")) == 0)
|
||||
{
|
||||
success = true;
|
||||
@@ -445,27 +394,3 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
SendStatus(source, status);
|
||||
yield();
|
||||
}
|
||||
|
||||
void printDirectory(File dir, int numTabs) {
|
||||
while (true) {
|
||||
|
||||
File entry = dir.openNextFile();
|
||||
if (! entry) {
|
||||
// no more files
|
||||
break;
|
||||
}
|
||||
for (uint8_t i = 0; i < numTabs; i++) {
|
||||
Serial.print('\t');
|
||||
}
|
||||
Serial.print(entry.name());
|
||||
if (entry.isDirectory()) {
|
||||
Serial.println("/");
|
||||
printDirectory(entry, numTabs + 1);
|
||||
} else {
|
||||
// files have sizes, directories do not
|
||||
Serial.print("\t\t");
|
||||
Serial.println(entry.size(), DEC);
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,8 @@ boolean sendData(struct EventStruct *event)
|
||||
if (Settings.GlobalSync && Settings.TaskDeviceGlobalSync[event->TaskIndex])
|
||||
SendUDPTaskData(0, event->TaskIndex, event->TaskIndex);
|
||||
|
||||
// if (!Settings.TaskDeviceSendData[event->TaskIndex])
|
||||
// return false;
|
||||
if (!Settings.TaskDeviceSendData[event->TaskIndex])
|
||||
return false;
|
||||
|
||||
if (Settings.MessageDelay != 0)
|
||||
{
|
||||
@@ -30,18 +30,11 @@ boolean sendData(struct EventStruct *event)
|
||||
|
||||
LoadTaskSettings(event->TaskIndex); // could have changed during background tasks.
|
||||
|
||||
for (byte x=0; x < CONTROLLER_MAX; x++)
|
||||
if (Settings.Protocol)
|
||||
{
|
||||
event->ControllerIndex = x;
|
||||
event->idx = Settings.TaskDeviceID[x][event->TaskIndex];
|
||||
|
||||
if (Settings.TaskDeviceSendData[event->ControllerIndex][event->TaskIndex] && Settings.ControllerEnabled[event->ControllerIndex] && Settings.Protocol[event->ControllerIndex])
|
||||
{
|
||||
event->ProtocolIndex = getProtocolIndex(Settings.Protocol[event->ControllerIndex]);
|
||||
CPlugin_ptr[event->ProtocolIndex](CPLUGIN_PROTOCOL_SEND, event, dummyString);
|
||||
}
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol);
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_PROTOCOL_SEND, event, dummyString);
|
||||
}
|
||||
|
||||
PluginCall(PLUGIN_EVENT_OUT, event, dummyString);
|
||||
lastSend = millis();
|
||||
}
|
||||
@@ -66,7 +59,7 @@ void callback(char* c_topic, byte* b_payload, unsigned int length) {
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.String1 = c_topic;
|
||||
TempEvent.String2 = c_payload;
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[0]);
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol);
|
||||
CPlugin_ptr[ProtocolIndex](CPLUGIN_PROTOCOL_RECV, &TempEvent, dummyString);
|
||||
}
|
||||
|
||||
@@ -76,11 +69,8 @@ void callback(char* c_topic, byte* b_payload, unsigned int length) {
|
||||
\*********************************************************************************************/
|
||||
void MQTTConnect()
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(0, (byte*)&ControllerSettings, sizeof(ControllerSettings)); // todo index is now fixed to 0
|
||||
|
||||
IPAddress MQTTBrokerIP(ControllerSettings.IP);
|
||||
MQTTclient.setServer(MQTTBrokerIP, ControllerSettings.Port);
|
||||
IPAddress MQTTBrokerIP(Settings.Controller_IP);
|
||||
MQTTclient.setServer(MQTTBrokerIP, Settings.ControllerPort);
|
||||
MQTTclient.setCallback(callback);
|
||||
|
||||
// MQTT needs a unique clientname to subscribe to broker
|
||||
@@ -88,17 +78,22 @@ void MQTTConnect()
|
||||
clientid += Settings.Unit;
|
||||
String subscribeTo = "";
|
||||
|
||||
String LWTTopic = ControllerSettings.Subscribe;
|
||||
LWTTopic.replace(F("/#"), F("/status"));
|
||||
LWTTopic.replace(F("%sysname%"), Settings.Name);
|
||||
String LWTTopic = Settings.MQTTsubscribe;
|
||||
LWTTopic.replace("/#", "/status");
|
||||
LWTTopic.replace("%sysname%", Settings.Name);
|
||||
|
||||
for (byte x = 1; x < 3; x++)
|
||||
{
|
||||
String log = "";
|
||||
boolean MQTTresult = false;
|
||||
|
||||
//boolean connect(const char* id);
|
||||
//boolean connect(const char* id, const char* user, const char* pass);
|
||||
//boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
//boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
|
||||
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0))
|
||||
MQTTresult = MQTTclient.connect(clientid.c_str(), SecuritySettings.ControllerUser[0], SecuritySettings.ControllerPassword[0], LWTTopic.c_str(), 0, 0, "Connection Lost");
|
||||
MQTTresult = MQTTclient.connect(clientid.c_str(), SecuritySettings.ControllerUser, SecuritySettings.ControllerPassword, LWTTopic.c_str(), 0, 0, "Connection Lost");
|
||||
else
|
||||
MQTTresult = MQTTclient.connect(clientid.c_str(), LWTTopic.c_str(), 0, 0, "Connection Lost");
|
||||
|
||||
@@ -106,8 +101,8 @@ void MQTTConnect()
|
||||
{
|
||||
log = F("MQTT : Connected to broker");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
subscribeTo = ControllerSettings.Subscribe;
|
||||
subscribeTo.replace(F("%sysname%"), Settings.Name);
|
||||
subscribeTo = Settings.MQTTsubscribe;
|
||||
subscribeTo.replace("%sysname%", Settings.Name);
|
||||
MQTTclient.subscribe(subscribeTo.c_str());
|
||||
log = F("Subscribed to: ");
|
||||
log += subscribeTo;
|
||||
@@ -130,7 +125,7 @@ void MQTTConnect()
|
||||
\*********************************************************************************************/
|
||||
void MQTTCheck()
|
||||
{
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[0]);
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol);
|
||||
if (Protocol[ProtocolIndex].usesMQTT)
|
||||
if (!MQTTclient.connected())
|
||||
{
|
||||
@@ -173,14 +168,11 @@ void SendStatus(byte source, String status)
|
||||
\*********************************************************************************************/
|
||||
void MQTTStatus(String& status)
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(0, (byte*)&ControllerSettings, sizeof(ControllerSettings)); // todo index is now fixed to 0
|
||||
|
||||
String pubname = ControllerSettings.Subscribe;
|
||||
pubname.replace(F("/#"), F("/status"));
|
||||
pubname.replace(F("%sysname%"), Settings.Name);
|
||||
String pubname = Settings.MQTTsubscribe;
|
||||
pubname.replace("/#", "/status");
|
||||
pubname.replace("%sysname%", Settings.Name);
|
||||
MQTTclient.publish(pubname.c_str(), status.c_str(),Settings.MQTTRetainFlag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+237
-365
@@ -104,59 +104,30 @@
|
||||
|
||||
#define UNIT 0
|
||||
|
||||
#define FEATURE_TIME true
|
||||
#define FEATURE_SSDP true
|
||||
|
||||
// Enable FEATURE_ADC_VCC to measure supply voltage using the analog pin
|
||||
// Please note that the TOUT pin has to be disconnected in this mode
|
||||
// Use the "System Info" device to read the VCC value
|
||||
#define FEATURE_ADC_VCC false
|
||||
|
||||
//enable Arduino OTA updating.
|
||||
//Note: This adds around 10kb to the firmware size, and 1kb extra ram.
|
||||
//Normally only enabled for dev environment, since its helpfull while developing.
|
||||
// #define FEATURE_ARDUINO_OTA
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// DO NOT CHANGE ANYTHING BELOW THIS LINE
|
||||
// ********************************************************************************
|
||||
#define ESP_PROJECT_PID 2016110801L
|
||||
#define VERSION 2
|
||||
#define BUILD 20000 // git version 2.0.0
|
||||
#define BUILD_NOTES " - Mega"
|
||||
|
||||
#ifndef BUILD_GIT
|
||||
#define BUILD_GIT "(custom)"
|
||||
#endif
|
||||
|
||||
#define MAX_FLASHWRITES_PER_DAY 100 // per 24 hour window
|
||||
#define ESP_PROJECT_PID 2015050101L
|
||||
#define ESP_EASY
|
||||
#define VERSION 9
|
||||
#define BUILD 148
|
||||
#define BUILD_NOTES ""
|
||||
#define FEATURE_SPIFFS false
|
||||
|
||||
#define NODE_TYPE_ID_ESP_EASY_STD 1
|
||||
#define NODE_TYPE_ID_ESP_EASYM_STD 17
|
||||
#define NODE_TYPE_ID_ESP_EASY32_STD 33
|
||||
#define NODE_TYPE_ID_ARDUINO_EASY_STD 65
|
||||
#define NODE_TYPE_ID_NANO_EASY_STD 81
|
||||
#define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASYM_STD
|
||||
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
#define PLUGIN_INIT 2
|
||||
#define PLUGIN_READ 3
|
||||
#define PLUGIN_ONCE_A_SECOND 4
|
||||
#define PLUGIN_TEN_PER_SECOND 5
|
||||
#define PLUGIN_DEVICE_ADD 6
|
||||
#define PLUGIN_EVENTLIST_ADD 7
|
||||
#define PLUGIN_WEBFORM_SAVE 8
|
||||
#define PLUGIN_WEBFORM_LOAD 9
|
||||
#define PLUGIN_WEBFORM_SHOW_VALUES 10
|
||||
#define PLUGIN_GET_DEVICENAME 11
|
||||
#define PLUGIN_GET_DEVICEVALUENAMES 12
|
||||
#define PLUGIN_WRITE 13
|
||||
#define PLUGIN_EVENT_OUT 14
|
||||
#define PLUGIN_WEBFORM_SHOW_CONFIG 15
|
||||
#define PLUGIN_SERIAL_IN 16
|
||||
#define PLUGIN_UDP_IN 17
|
||||
#define PLUGIN_CLOCK_IN 18
|
||||
#define PLUGIN_TIMER_IN 19
|
||||
#define PLUGIN_FIFTY_PER_SECOND 20
|
||||
#define PLUGIN_REMOTE_CONFIG 21
|
||||
#define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASY_STD
|
||||
|
||||
#define CPLUGIN_PROTOCOL_ADD 1
|
||||
#define CPLUGIN_PROTOCOL_TEMPLATE 2
|
||||
@@ -166,13 +137,6 @@
|
||||
#define CPLUGIN_WEBFORM_SAVE 6
|
||||
#define CPLUGIN_WEBFORM_LOAD 7
|
||||
|
||||
#define NPLUGIN_PROTOCOL_ADD 1
|
||||
#define NPLUGIN_GET_DEVICENAME 2
|
||||
#define NPLUGIN_WEBFORM_SAVE 3
|
||||
#define NPLUGIN_WEBFORM_LOAD 4
|
||||
#define NPLUGIN_WRITE 5
|
||||
#define NPLUGIN_NOTIFY 6
|
||||
|
||||
#define LOG_LEVEL_ERROR 1
|
||||
#define LOG_LEVEL_INFO 2
|
||||
#define LOG_LEVEL_DEBUG 3
|
||||
@@ -182,9 +146,7 @@
|
||||
#define CMD_WIFI_DISCONNECT 135
|
||||
|
||||
#define DEVICES_MAX 64
|
||||
#define TASKS_MAX 12 // max 12!
|
||||
#define CONTROLLER_MAX 3 // max 4!
|
||||
#define NOTIFICATION_MAX 3 // max 4!
|
||||
#define TASKS_MAX 12
|
||||
#define VARS_PER_TASK 4
|
||||
#define PLUGIN_MAX 64
|
||||
#define PLUGIN_CONFIGVAR_MAX 8
|
||||
@@ -192,7 +154,6 @@
|
||||
#define PLUGIN_CONFIGLONGVAR_MAX 4
|
||||
#define PLUGIN_EXTRACONFIGVAR_MAX 16
|
||||
#define CPLUGIN_MAX 16
|
||||
#define NPLUGIN_MAX 4
|
||||
#define UNIT_MAX 32 // Only relevant for UDP unicast message 'sweeps' and the nodelist.
|
||||
#define RULES_TIMER_MAX 8
|
||||
#define SYSTEM_TIMER_MAX 8
|
||||
@@ -200,7 +161,6 @@
|
||||
#define PINSTATE_TABLE_MAX 32
|
||||
#define RULES_MAX_SIZE 2048
|
||||
#define RULES_MAX_NESTING_LEVEL 3
|
||||
#define RULESETS_MAX 4
|
||||
|
||||
#define PIN_MODE_UNDEFINED 0
|
||||
#define PIN_MODE_INPUT 1
|
||||
@@ -229,6 +189,26 @@
|
||||
#define SENSOR_TYPE_LONG 20
|
||||
#define SENSOR_TYPE_WIND 21
|
||||
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
#define PLUGIN_INIT 2
|
||||
#define PLUGIN_READ 3
|
||||
#define PLUGIN_ONCE_A_SECOND 4
|
||||
#define PLUGIN_TEN_PER_SECOND 5
|
||||
#define PLUGIN_DEVICE_ADD 6
|
||||
#define PLUGIN_EVENTLIST_ADD 7
|
||||
#define PLUGIN_WEBFORM_SAVE 8
|
||||
#define PLUGIN_WEBFORM_LOAD 9
|
||||
#define PLUGIN_WEBFORM_SHOW_VALUES 10
|
||||
#define PLUGIN_GET_DEVICENAME 11
|
||||
#define PLUGIN_GET_DEVICEVALUENAMES 12
|
||||
#define PLUGIN_WRITE 13
|
||||
#define PLUGIN_EVENT_OUT 14
|
||||
#define PLUGIN_WEBFORM_SHOW_CONFIG 15
|
||||
#define PLUGIN_SERIAL_IN 16
|
||||
#define PLUGIN_UDP_IN 17
|
||||
#define PLUGIN_CLOCK_IN 18
|
||||
#define PLUGIN_TIMER_IN 19
|
||||
|
||||
#define VALUE_SOURCE_SYSTEM 1
|
||||
#define VALUE_SOURCE_SERIAL 2
|
||||
#define VALUE_SOURCE_HTTP 3
|
||||
@@ -237,18 +217,9 @@
|
||||
|
||||
#define BOOT_CAUSE_MANUAL_REBOOT 0
|
||||
#define BOOT_CAUSE_COLD_BOOT 1
|
||||
#define BOOT_CAUSE_DEEP_SLEEP 2
|
||||
#define BOOT_CAUSE_EXT_WD 10
|
||||
|
||||
#define DAT_TASKS_SIZE 2048
|
||||
#define DAT_TASKS_CUSTOM_OFFSET 1024
|
||||
#define DAT_CONTROLLER_SIZE 1024
|
||||
#define DAT_NOTIFICATION_SIZE 1024
|
||||
|
||||
#define DAT_OFFSET_TASKS 4096 // each task = 2k, (1024 basic + 1024 bytes custom), 12 max
|
||||
#define DAT_OFFSET_CONTROLLER 28672 // each controller = 1k, 4 max
|
||||
#define DAT_OFFSET_CUSTOMCONTROLLER 32768 // custom controller config = 4k, currently only one can use it.
|
||||
|
||||
#include "Version.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <WiFiUdp.h>
|
||||
@@ -259,9 +230,9 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
#include <Servo.h>
|
||||
#define FS_NO_GLOBALS
|
||||
#if FEATURE_SPIFFS
|
||||
#include <FS.h>
|
||||
#include <SD.h>
|
||||
#endif
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
ESP8266HTTPUpdateServer httpUpdater(true);
|
||||
#include <base64.h>
|
||||
@@ -280,13 +251,6 @@ extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
bool ArduinoOTAtriggered=false;
|
||||
#endif
|
||||
|
||||
// Setup DNS, only used if the ESP has no valid WiFi config
|
||||
const byte DNS_PORT = 53;
|
||||
IPAddress apIP(192, 168, 4, 1);
|
||||
@@ -305,6 +269,7 @@ ESP8266WebServer WebServer(80);
|
||||
// syslog stuff
|
||||
WiFiUDP portUDP;
|
||||
|
||||
#define FLASH_EEPROM_SIZE 4096
|
||||
extern "C" {
|
||||
#include "spi_flash.h"
|
||||
}
|
||||
@@ -317,11 +282,9 @@ struct SecurityStruct
|
||||
{
|
||||
char WifiSSID[32];
|
||||
char WifiKey[64];
|
||||
char WifiSSID2[32];
|
||||
char WifiKey2[64];
|
||||
char WifiAPKey[64];
|
||||
char ControllerUser[CONTROLLER_MAX][26];
|
||||
char ControllerPassword[CONTROLLER_MAX][64];
|
||||
char ControllerUser[26];
|
||||
char ControllerPassword[64];
|
||||
char Password[26];
|
||||
} SecuritySettings;
|
||||
|
||||
@@ -329,90 +292,66 @@ struct SettingsStruct
|
||||
{
|
||||
unsigned long PID;
|
||||
int Version;
|
||||
int16_t Build;
|
||||
byte IP[4];
|
||||
byte Gateway[4];
|
||||
byte Subnet[4];
|
||||
byte DNS[4];
|
||||
byte IP_Octet;
|
||||
byte Unit;
|
||||
char Name[26];
|
||||
byte Controller_IP[4];
|
||||
unsigned int ControllerPort;
|
||||
byte IP_Octet;
|
||||
char NTPHost[64];
|
||||
unsigned long Delay;
|
||||
int8_t Pin_i2c_sda;
|
||||
int8_t Pin_i2c_scl;
|
||||
int8_t Pin_status_led;
|
||||
int8_t Pin_sd_cs;
|
||||
int8_t PinBootStates[17];
|
||||
byte Syslog_IP[4];
|
||||
unsigned int UDPPort;
|
||||
byte Protocol;
|
||||
byte IP[4];
|
||||
byte Gateway[4];
|
||||
byte Subnet[4];
|
||||
char Name[26];
|
||||
byte SyslogLevel;
|
||||
byte SerialLogLevel;
|
||||
byte WebLogLevel;
|
||||
byte SDLogLevel;
|
||||
unsigned long BaudRate;
|
||||
unsigned long MessageDelay;
|
||||
byte TaskDeviceNumber[TASKS_MAX];
|
||||
unsigned int TaskDeviceID[TASKS_MAX];
|
||||
int8_t TaskDevicePin1[TASKS_MAX];
|
||||
int8_t TaskDevicePin2[TASKS_MAX];
|
||||
byte TaskDevicePort[TASKS_MAX];
|
||||
boolean TaskDevicePin1PullUp[TASKS_MAX];
|
||||
int16_t TaskDevicePluginConfig[TASKS_MAX][PLUGIN_CONFIGVAR_MAX];
|
||||
boolean TaskDevicePin1Inversed[TASKS_MAX];
|
||||
byte deepSleep;
|
||||
char MQTTpublish[81];
|
||||
char MQTTsubscribe[81];
|
||||
boolean CustomCSS;
|
||||
float TaskDevicePluginConfigFloat[TASKS_MAX][PLUGIN_CONFIGFLOATVAR_MAX];
|
||||
long TaskDevicePluginConfigLong[TASKS_MAX][PLUGIN_CONFIGLONGVAR_MAX];
|
||||
boolean TaskDeviceSendData[TASKS_MAX];
|
||||
int16_t Build;
|
||||
byte DNS[4];
|
||||
int8_t TimeZone_OLD;
|
||||
char ControllerHostName[64];
|
||||
boolean UseNTP;
|
||||
boolean DST;
|
||||
byte WDI2CAddress;
|
||||
boolean TaskDeviceGlobalSync[TASKS_MAX];
|
||||
int8_t TaskDevicePin3[TASKS_MAX];
|
||||
byte TaskDeviceDataFeed[TASKS_MAX];
|
||||
int8_t PinBootStates[17];
|
||||
byte UseDNS;
|
||||
boolean UseRules;
|
||||
int8_t Pin_status_led;
|
||||
boolean UseSerial;
|
||||
unsigned long TaskDeviceTimer[TASKS_MAX];
|
||||
boolean UseSSDP;
|
||||
boolean UseNTP;
|
||||
unsigned long WireClockStretchLimit;
|
||||
boolean GlobalSync;
|
||||
unsigned long ConnectionFailuresThreshold;
|
||||
int16_t TimeZone;
|
||||
boolean MQTTRetainFlag;
|
||||
boolean InitSPI;
|
||||
byte Protocol[CONTROLLER_MAX];
|
||||
byte Notification[NOTIFICATION_MAX];
|
||||
byte TaskDeviceNumber[TASKS_MAX];
|
||||
unsigned int OLD_TaskDeviceID[TASKS_MAX];
|
||||
int8_t TaskDevicePin1[TASKS_MAX];
|
||||
int8_t TaskDevicePin2[TASKS_MAX];
|
||||
int8_t TaskDevicePin3[TASKS_MAX];
|
||||
byte TaskDevicePort[TASKS_MAX];
|
||||
boolean TaskDevicePin1PullUp[TASKS_MAX];
|
||||
int16_t TaskDevicePluginConfig[TASKS_MAX][PLUGIN_CONFIGVAR_MAX];
|
||||
boolean TaskDevicePin1Inversed[TASKS_MAX];
|
||||
float TaskDevicePluginConfigFloat[TASKS_MAX][PLUGIN_CONFIGFLOATVAR_MAX];
|
||||
long TaskDevicePluginConfigLong[TASKS_MAX][PLUGIN_CONFIGLONGVAR_MAX];
|
||||
boolean OLD_TaskDeviceSendData[TASKS_MAX];
|
||||
boolean TaskDeviceGlobalSync[TASKS_MAX];
|
||||
byte TaskDeviceDataFeed[TASKS_MAX];
|
||||
unsigned long TaskDeviceTimer[TASKS_MAX];
|
||||
boolean TaskDeviceEnabled[TASKS_MAX];
|
||||
boolean ControllerEnabled[CONTROLLER_MAX];
|
||||
boolean NotificationEnabled[NOTIFICATION_MAX];
|
||||
unsigned int TaskDeviceID[CONTROLLER_MAX][TASKS_MAX];
|
||||
boolean TaskDeviceSendData[CONTROLLER_MAX][TASKS_MAX];
|
||||
} Settings;
|
||||
|
||||
struct ControllerSettingsStruct
|
||||
{
|
||||
boolean UseDNS;
|
||||
byte IP[4];
|
||||
unsigned int Port;
|
||||
char HostName[65];
|
||||
char Publish[129];
|
||||
char Subscribe[129];
|
||||
};
|
||||
|
||||
struct NotificationSettingsStruct
|
||||
{
|
||||
char Server[65];
|
||||
unsigned int Port;
|
||||
char Domain[65];
|
||||
char Sender[65];
|
||||
char Receiver[65];
|
||||
char Subject[129];
|
||||
char Body[513];
|
||||
byte Pin1;
|
||||
byte Pin2;
|
||||
};
|
||||
|
||||
struct ExtraTaskSettingsStruct
|
||||
{
|
||||
byte TaskIndex;
|
||||
@@ -421,17 +360,12 @@ struct ExtraTaskSettingsStruct
|
||||
char TaskDeviceValueNames[VARS_PER_TASK][41];
|
||||
long TaskDevicePluginConfigLong[PLUGIN_EXTRACONFIGVAR_MAX];
|
||||
byte TaskDeviceValueDecimals[VARS_PER_TASK];
|
||||
int16_t TaskDevicePluginConfig[PLUGIN_EXTRACONFIGVAR_MAX];
|
||||
} ExtraTaskSettings;
|
||||
|
||||
struct EventStruct
|
||||
{
|
||||
byte Source;
|
||||
byte TaskIndex; // index position in TaskSettings array, 0-11
|
||||
byte ControllerIndex; // index position in Settings.Controller, 0-3
|
||||
byte ProtocolIndex; // index position in protocol array, depending on which controller plugins are loaded.
|
||||
byte NotificationIndex; // index position in Settings.Notification, 0-3
|
||||
byte NotificationProtocolIndex; // index position in notification array, depending on which controller plugins are loaded.
|
||||
byte TaskIndex;
|
||||
byte BaseVarIndex;
|
||||
int idx;
|
||||
byte sensorType;
|
||||
@@ -447,7 +381,7 @@ struct EventStruct
|
||||
struct LogStruct
|
||||
{
|
||||
unsigned long timeStamp;
|
||||
char* Message;
|
||||
String Message;
|
||||
} Logging[10];
|
||||
int logcount = -1;
|
||||
|
||||
@@ -477,16 +411,8 @@ struct ProtocolStruct
|
||||
boolean usesPassword;
|
||||
int defaultPort;
|
||||
boolean usesTemplate;
|
||||
boolean usesID;
|
||||
} Protocol[CPLUGIN_MAX];
|
||||
|
||||
struct NotificationStruct
|
||||
{
|
||||
byte Number;
|
||||
boolean usesMessaging;
|
||||
byte usesGPIO;
|
||||
} Notification[NPLUGIN_MAX];
|
||||
|
||||
struct NodeStruct
|
||||
{
|
||||
byte ip[4];
|
||||
@@ -519,21 +445,8 @@ struct pinStatesStruct
|
||||
uint16_t value;
|
||||
} pinStates[PINSTATE_TABLE_MAX];
|
||||
|
||||
struct RTCStruct
|
||||
{
|
||||
byte ID1;
|
||||
byte ID2;
|
||||
boolean valid;
|
||||
byte factoryResetCounter;
|
||||
byte deepSleepState;
|
||||
byte rebootCounter; //not used yet?
|
||||
byte flashDayCounter;
|
||||
unsigned long flashCounter;
|
||||
} RTC;
|
||||
|
||||
int deviceCount = -1;
|
||||
int protocolCount = -1;
|
||||
int notificationCount = -1;
|
||||
|
||||
boolean printToWeb = false;
|
||||
String printWebString = "";
|
||||
@@ -543,8 +456,8 @@ float UserVar[VARS_PER_TASK * TASKS_MAX];
|
||||
unsigned long RulesTimer[RULES_TIMER_MAX];
|
||||
|
||||
unsigned long timerSensor[TASKS_MAX];
|
||||
unsigned long timer;
|
||||
unsigned long timer100ms;
|
||||
unsigned long timer20ms;
|
||||
unsigned long timer1s;
|
||||
unsigned long timerwd;
|
||||
unsigned long lastSend;
|
||||
@@ -565,15 +478,13 @@ int WebLoggedInTimer = 300;
|
||||
boolean (*Plugin_ptr[PLUGIN_MAX])(byte, struct EventStruct*, String&);
|
||||
byte Plugin_id[PLUGIN_MAX];
|
||||
|
||||
boolean (*CPlugin_ptr[CPLUGIN_MAX])(byte, struct EventStruct*, String&);
|
||||
byte CPlugin_id[CPLUGIN_MAX];
|
||||
|
||||
boolean (*NPlugin_ptr[NPLUGIN_MAX])(byte, struct EventStruct*, String&);
|
||||
byte NPlugin_id[NPLUGIN_MAX];
|
||||
boolean (*CPlugin_ptr[PLUGIN_MAX])(byte, struct EventStruct*, String&);
|
||||
byte CPlugin_id[PLUGIN_MAX];
|
||||
|
||||
String dummyString = "";
|
||||
|
||||
byte lastBootCause = BOOT_CAUSE_MANUAL_REBOOT;
|
||||
boolean systemOK = false;
|
||||
byte lastBootCause = 0;
|
||||
|
||||
boolean wifiSetup = false;
|
||||
boolean wifiSetupConnect = false;
|
||||
@@ -584,52 +495,34 @@ unsigned long loopCounter = 0;
|
||||
unsigned long loopCounterLast = 0;
|
||||
unsigned long loopCounterMax = 1;
|
||||
|
||||
unsigned long dailyResetCounter = 0;
|
||||
unsigned long flashWrites = 0;
|
||||
|
||||
String eventBuffer = "";
|
||||
|
||||
uint16_t lowestRAM = 0;
|
||||
byte lowestRAMid=0;
|
||||
/*
|
||||
1 savetoflash - obsolete
|
||||
2 loadfrom flash - obsolete
|
||||
3 zerofillflash - obsolete
|
||||
4 rulesprocessing
|
||||
5 handle_download
|
||||
6 handle_css
|
||||
7 handlefileupload
|
||||
8 handle_rules
|
||||
9 handle_devices
|
||||
*/
|
||||
// Blynk_get prototype
|
||||
boolean Blynk_get(String command,float *data = NULL );
|
||||
|
||||
/*********************************************************************************************\
|
||||
* SETUP
|
||||
\*********************************************************************************************/
|
||||
void setup()
|
||||
{
|
||||
lowestRAM = FreeMem();
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
initLog();
|
||||
|
||||
|
||||
if (SpiffsSectors() < 32)
|
||||
if (SpiffsSectors() == 0)
|
||||
{
|
||||
Serial.println(F("\nNo (or too small) SPIFFS area..\nSystem Halted\nPlease reflash with 128k SPIFFS minimum!"));
|
||||
Serial.println(F("\nNo SPIFFS area..\nSystem Halted\nPlease reflash with SPIFFS"));
|
||||
while (true)
|
||||
delay(1);
|
||||
}
|
||||
|
||||
#if FEATURE_SPIFFS
|
||||
fileSystemCheck();
|
||||
#endif
|
||||
|
||||
emergencyReset();
|
||||
|
||||
String log = F("\n\n\rINIT : Booting version: ");
|
||||
log += BUILD_GIT;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
fileSystemCheck();
|
||||
LoadSettings();
|
||||
|
||||
if (strcasecmp(SecuritySettings.WifiSSID, "ssid") == 0)
|
||||
wifiSetup = true;
|
||||
|
||||
@@ -637,7 +530,11 @@ void setup()
|
||||
|
||||
// if different version, eeprom settings structure has changed. Full Reset needed
|
||||
// on a fresh ESP module eeprom values are set to 255. Version results into -1 (signed int)
|
||||
if (Settings.Version != VERSION || Settings.PID != ESP_PROJECT_PID)
|
||||
if (Settings.Version == VERSION && Settings.PID == ESP_PROJECT_PID)
|
||||
{
|
||||
systemOK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct Serial is allowed here, since this is only an emergency task.
|
||||
Serial.print(F("\nPID:"));
|
||||
@@ -649,113 +546,117 @@ void setup()
|
||||
ResetFactory();
|
||||
}
|
||||
|
||||
if (Settings.UseSerial)
|
||||
Serial.begin(Settings.BaudRate);
|
||||
|
||||
if (Settings.Build != BUILD)
|
||||
BuildFixes();
|
||||
|
||||
|
||||
log = F("INIT : Free RAM:");
|
||||
log += FreeMem();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
if (Settings.UseSerial && Settings.SerialLogLevel >= LOG_LEVEL_DEBUG_MORE)
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
hardwareInit();
|
||||
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
WifiAPconfig();
|
||||
if (!WifiConnect(true,3))
|
||||
WifiConnect(false,3);
|
||||
|
||||
|
||||
//After booting, we want all the tasks to run without delaying more than neccesary.
|
||||
//Plugins that need an initial startup delay need to overwrite their initial timerSensor value in PLUGIN_INIT
|
||||
//They should also check if we returned from deep sleep so that they can skip the delay in that case.
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
if (Settings.TaskDeviceTimer[x] !=0)
|
||||
timerSensor[x] = millis() + (x * Settings.MessageDelay);
|
||||
|
||||
timer100ms = 0; // timer for periodic actions 10 x per/sec
|
||||
timer1s = 0; // timer for periodic actions once per/sec
|
||||
timerwd = 0; // timer for watchdog once per 30 sec
|
||||
|
||||
PluginInit();
|
||||
CPluginInit();
|
||||
NPluginInit();
|
||||
|
||||
WebServerInit();
|
||||
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
ArduinoOTAInit();
|
||||
#endif
|
||||
|
||||
// setup UDP
|
||||
if (Settings.UDPPort != 0)
|
||||
portUDP.begin(Settings.UDPPort);
|
||||
|
||||
// Setup MQTT Client
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[0]);
|
||||
if (Protocol[ProtocolIndex].usesMQTT)
|
||||
MQTTConnect();
|
||||
|
||||
sendSysInfoUDP(3);
|
||||
|
||||
//warm boot
|
||||
if (readFromRTC())
|
||||
if (systemOK)
|
||||
{
|
||||
readUserVarFromRTC();
|
||||
if (RTC.deepSleepState == 1)
|
||||
if (Settings.UseSerial)
|
||||
Serial.begin(Settings.BaudRate);
|
||||
|
||||
if (Settings.Build != BUILD)
|
||||
BuildFixes();
|
||||
|
||||
String log = F("\nINIT : Booting Build nr:");
|
||||
log += BUILD;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
if (Settings.UseSerial && Settings.SerialLogLevel >= LOG_LEVEL_DEBUG_MORE)
|
||||
Serial.setDebugOutput(true);
|
||||
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
WifiAPconfig();
|
||||
WifiConnect(3);
|
||||
|
||||
hardwareInit();
|
||||
PluginInit();
|
||||
CPluginInit();
|
||||
|
||||
WebServerInit();
|
||||
|
||||
// setup UDP
|
||||
if (Settings.UDPPort != 0)
|
||||
portUDP.begin(Settings.UDPPort);
|
||||
|
||||
// Setup MQTT Client
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol);
|
||||
if (Protocol[ProtocolIndex].usesMQTT)
|
||||
MQTTConnect();
|
||||
|
||||
sendSysInfoUDP(3);
|
||||
|
||||
log = F("INIT : Boot OK");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
if (Settings.deepSleep)
|
||||
{
|
||||
log = F("INIT : Rebooted from deepsleep");
|
||||
lastBootCause=BOOT_CAUSE_DEEP_SLEEP;
|
||||
log = F("INIT : Deep sleep enabled");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
byte bootMode = 0;
|
||||
if (readFromRTC(&bootMode))
|
||||
{
|
||||
if (bootMode == 1)
|
||||
log = F("INIT : Reboot from deepsleep");
|
||||
else
|
||||
log = F("INIT : Normal boot");
|
||||
}
|
||||
else
|
||||
log = F("INIT : Normal boot");
|
||||
}
|
||||
//cold boot (RTC memory empty)
|
||||
else
|
||||
{
|
||||
RTC.factoryResetCounter=0;
|
||||
RTC.deepSleepState=0;
|
||||
RTC.rebootCounter=0;
|
||||
RTC.flashDayCounter=0;
|
||||
RTC.flashCounter=0;
|
||||
saveToRTC();
|
||||
{
|
||||
// cold boot situation
|
||||
if (lastBootCause == 0) // only set this if not set earlier during boot stage.
|
||||
lastBootCause = BOOT_CAUSE_COLD_BOOT;
|
||||
log = F("INIT : Cold Boot");
|
||||
}
|
||||
|
||||
// cold boot situation
|
||||
if (lastBootCause == BOOT_CAUSE_MANUAL_REBOOT) // only set this if not set earlier during boot stage.
|
||||
lastBootCause = BOOT_CAUSE_COLD_BOOT;
|
||||
log = F("INIT : Cold Boot");
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
saveToRTC(0);
|
||||
|
||||
// Setup timers
|
||||
if (bootMode == 0)
|
||||
{
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
if (Settings.TaskDeviceTimer[x] !=0)
|
||||
timerSensor[x] = millis() + 30000 + (x * Settings.MessageDelay);
|
||||
|
||||
if (Settings.UseNTP)
|
||||
initTime();
|
||||
timer = millis() + 30000; // startup delay 30 sec
|
||||
}
|
||||
else
|
||||
{
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
timerSensor[x] = millis() + 0;
|
||||
timer = millis() + 0; // no startup from deepsleep wake up
|
||||
}
|
||||
|
||||
#if FEATURE_ADC_VCC
|
||||
vcc = ESP.getVcc() / 1000.0;
|
||||
timer100ms = millis() + 100; // timer for periodic actions 10 x per/sec
|
||||
timer1s = millis() + 1000; // timer for periodic actions once per/sec
|
||||
timerwd = millis() + 30000; // timer for watchdog once per 30 sec
|
||||
|
||||
#if FEATURE_TIME
|
||||
if (Settings.UseNTP)
|
||||
initTime();
|
||||
#endif
|
||||
|
||||
// Start DNS, only used if the ESP has no valid WiFi config
|
||||
// It will reply with it's own address on all DNS requests
|
||||
// (captive portal concept)
|
||||
if (wifiSetup)
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
#if FEATURE_ADC_VCC
|
||||
vcc = ESP.getVcc() / 1000.0;
|
||||
#endif
|
||||
|
||||
// Start DNS, only used if the ESP has no valid WiFi config
|
||||
// It will reply with it's own address on all DNS requests
|
||||
// (captive portal concept)
|
||||
if (wifiSetup)
|
||||
dnsServer.start(DNS_PORT, "*", apIP);
|
||||
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
String event = F("System#Boot");
|
||||
rulesProcessing(event);
|
||||
}
|
||||
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
String event = F("System#Boot");
|
||||
rulesProcessing(event);
|
||||
}
|
||||
|
||||
RTC.deepSleepState=0;
|
||||
saveToRTC();
|
||||
|
||||
else
|
||||
{
|
||||
Serial.println(F("Entered Rescue mode!"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -769,7 +670,7 @@ void loop()
|
||||
if (wifiSetupConnect)
|
||||
{
|
||||
// try to connect for setup wizard
|
||||
WifiConnect(true,1);
|
||||
WifiConnect(1);
|
||||
wifiSetupConnect = false;
|
||||
}
|
||||
|
||||
@@ -778,48 +679,25 @@ void loop()
|
||||
if (!PluginCall(PLUGIN_SERIAL_IN, 0, dummyString))
|
||||
serial();
|
||||
|
||||
// Deep sleep mode, just run all tasks one time and go back to sleep as fast as possible
|
||||
if (Settings.deepSleep)
|
||||
if (systemOK)
|
||||
{
|
||||
run50TimesPerSecond();
|
||||
run10TimesPerSecond();
|
||||
runEach30Seconds();
|
||||
runOncePerSecond();
|
||||
deepSleep(Settings.Delay);
|
||||
//deepsleep will never return, its a special kind of reboot
|
||||
}
|
||||
//normal mode, run each task when its time
|
||||
else
|
||||
{
|
||||
|
||||
if (millis() > timer20ms)
|
||||
run50TimesPerSecond();
|
||||
|
||||
if (millis() > timer100ms)
|
||||
run10TimesPerSecond();
|
||||
|
||||
if (millis() > timerwd)
|
||||
runEach30Seconds();
|
||||
|
||||
if (millis() > timer1s)
|
||||
runOncePerSecond();
|
||||
|
||||
if (millis() > timerwd)
|
||||
runEach30Seconds();
|
||||
|
||||
backgroundtasks();
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
delay(1);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Tasks that run 50 times per second
|
||||
\*********************************************************************************************/
|
||||
|
||||
void run50TimesPerSecond()
|
||||
{
|
||||
timer20ms = millis() + 20;
|
||||
PluginCall(PLUGIN_FIFTY_PER_SECOND, 0, dummyString);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Tasks that run 10 times per second
|
||||
\*********************************************************************************************/
|
||||
@@ -843,16 +721,6 @@ void run10TimesPerSecond()
|
||||
\*********************************************************************************************/
|
||||
void runOncePerSecond()
|
||||
{
|
||||
dailyResetCounter++;
|
||||
if (dailyResetCounter > 86400) // 1 day elapsed... //86400
|
||||
{
|
||||
RTC.flashDayCounter=0;
|
||||
saveToRTC();
|
||||
dailyResetCounter=0;
|
||||
String log = F("SYS : Reset 24h counters");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
timer1s = millis() + 1000;
|
||||
|
||||
checkSensors();
|
||||
@@ -879,10 +747,11 @@ void runOncePerSecond()
|
||||
cmd_within_mainloop = 0;
|
||||
}
|
||||
|
||||
#if FEATURE_TIME
|
||||
// clock events
|
||||
if (Settings.UseNTP)
|
||||
checkTime();
|
||||
|
||||
#endif
|
||||
unsigned long timer = micros();
|
||||
PluginCall(PLUGIN_ONCE_A_SECOND, 0, dummyString);
|
||||
|
||||
@@ -934,8 +803,10 @@ void runEach30Seconds()
|
||||
sendSysInfoUDP(1);
|
||||
refreshNodeList();
|
||||
MQTTCheck();
|
||||
#if FEATURE_SSDP
|
||||
if (Settings.UseSSDP)
|
||||
SSDP_update();
|
||||
#endif
|
||||
#if FEATURE_ADC_VCC
|
||||
vcc = ESP.getVcc() / 1000.0;
|
||||
#endif
|
||||
@@ -954,34 +825,48 @@ void runEach30Seconds()
|
||||
\*********************************************************************************************/
|
||||
void checkSensors()
|
||||
{
|
||||
//check all the devices and only run the sendtask if its time, or we if we used deep sleep mode
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
// Check sensors and send data to controller when sensor timer has elapsed
|
||||
// If deepsleep, use the single timer
|
||||
if (Settings.deepSleep)
|
||||
{
|
||||
if (
|
||||
(Settings.TaskDeviceTimer[x] != 0) &&
|
||||
(Settings.deepSleep || (millis() > timerSensor[x]))
|
||||
)
|
||||
if (millis() > timer)
|
||||
{
|
||||
timerSensor[x] = millis() + Settings.TaskDeviceTimer[x] * 1000;
|
||||
if (timerSensor[x] == 0) // small fix if result is 0, else timer will be stopped...
|
||||
timerSensor[x] = 1;
|
||||
SensorSendTask(x);
|
||||
timer = millis() + Settings.Delay * 1000;
|
||||
SensorSend();
|
||||
saveToRTC(1);
|
||||
String log = F("Enter deep sleep...");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
String event = F("System#Sleep");
|
||||
rulesProcessing(event);
|
||||
ESP.deepSleep(Settings.Delay * 1000000, WAKE_RF_DEFAULT); // Sleep for set delay
|
||||
}
|
||||
}
|
||||
else // use individual timers for tasks
|
||||
{
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
{
|
||||
if ((Settings.TaskDeviceTimer[x] != 0) && (millis() > timerSensor[x]))
|
||||
{
|
||||
timerSensor[x] = millis() + Settings.TaskDeviceTimer[x] * 1000;
|
||||
if (timerSensor[x] == 0) // small fix if result is 0, else timer will be stopped...
|
||||
timerSensor[x] = 1;
|
||||
SensorSendTask(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
saveUserVarToRTC();
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* send all sensordata
|
||||
\*********************************************************************************************/
|
||||
// void SensorSendAll()
|
||||
// {
|
||||
// for (byte x = 0; x < TASKS_MAX; x++)
|
||||
// {
|
||||
// SensorSendTask(x);
|
||||
// }
|
||||
// }
|
||||
void SensorSend()
|
||||
{
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
{
|
||||
SensorSendTask(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
@@ -989,7 +874,7 @@ void checkSensors()
|
||||
\*********************************************************************************************/
|
||||
void SensorSendTask(byte TaskIndex)
|
||||
{
|
||||
if (Settings.TaskDeviceEnabled[TaskIndex])
|
||||
if (Settings.TaskDeviceID[TaskIndex] != 0)
|
||||
{
|
||||
byte varIndex = TaskIndex * VARS_PER_TASK;
|
||||
|
||||
@@ -1000,7 +885,7 @@ void SensorSendTask(byte TaskIndex)
|
||||
struct EventStruct TempEvent;
|
||||
TempEvent.TaskIndex = TaskIndex;
|
||||
TempEvent.BaseVarIndex = varIndex;
|
||||
// TempEvent.idx = Settings.TaskDeviceID[TaskIndex]; todo check
|
||||
TempEvent.idx = Settings.TaskDeviceID[TaskIndex];
|
||||
TempEvent.sensorType = Device[DeviceIndex].VType;
|
||||
|
||||
float preValue[VARS_PER_TASK]; // store values before change, in case we need it in the formula
|
||||
@@ -1023,8 +908,8 @@ void SensorSendTask(byte TaskIndex)
|
||||
float value = UserVar[varIndex + varNr];
|
||||
float result = 0;
|
||||
String svalue = String(value);
|
||||
formula.replace(F("%pvalue%"), spreValue);
|
||||
formula.replace(F("%value%"), svalue);
|
||||
formula.replace("%pvalue%", spreValue);
|
||||
formula.replace("%value%", svalue);
|
||||
byte error = Calculate(formula.c_str(), &result);
|
||||
if (error == 0)
|
||||
UserVar[varIndex + varNr] = result;
|
||||
@@ -1135,18 +1020,5 @@ void backgroundtasks()
|
||||
MQTTclient.loop();
|
||||
statusLED(false);
|
||||
checkUDP();
|
||||
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
ArduinoOTA.handle();
|
||||
|
||||
//once OTA is triggered, only handle that and dont do other stuff. (otherwise it fails)
|
||||
while (ArduinoOTAtriggered)
|
||||
{
|
||||
yield();
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
yield();
|
||||
}
|
||||
@@ -1,95 +1,78 @@
|
||||
/********************************************************************************************\
|
||||
* Initialize specific hardware setings (only global ones, others are set through devices)
|
||||
\*********************************************************************************************/
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
|
||||
// set GPIO pins state if not set to default
|
||||
for (byte x=0; x < 17; x++)
|
||||
if (Settings.PinBootStates[x] != 0)
|
||||
switch(Settings.PinBootStates[x])
|
||||
{
|
||||
case 1:
|
||||
pinMode(x,OUTPUT);
|
||||
digitalWrite(x,LOW);
|
||||
setPinState(1, x, PIN_MODE_OUTPUT, LOW);
|
||||
break;
|
||||
case 2:
|
||||
pinMode(x,OUTPUT);
|
||||
digitalWrite(x,HIGH);
|
||||
setPinState(1, x, PIN_MODE_OUTPUT, HIGH);
|
||||
break;
|
||||
case 3:
|
||||
pinMode(x,INPUT_PULLUP);
|
||||
setPinState(1, x, PIN_MODE_INPUT, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// configure hardware pins according to eeprom settings.
|
||||
if (Settings.Pin_i2c_sda != -1)
|
||||
{
|
||||
String log = F("INIT : I2C");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
Wire.begin(Settings.Pin_i2c_sda, Settings.Pin_i2c_scl);
|
||||
if(Settings.WireClockStretchLimit)
|
||||
{
|
||||
String log = F("INIT : I2C custom clockstretchlimit:");
|
||||
log += Settings.WireClockStretchLimit;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
Wire.setClockStretchLimit(Settings.WireClockStretchLimit);
|
||||
}
|
||||
}
|
||||
|
||||
// I2C Watchdog boot status check
|
||||
if (Settings.WDI2CAddress != 0)
|
||||
{
|
||||
delay(500);
|
||||
Wire.beginTransmission(Settings.WDI2CAddress);
|
||||
Wire.write(0x83); // command to set pointer
|
||||
Wire.write(17); // pointer value to status byte
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(Settings.WDI2CAddress, (uint8_t)1);
|
||||
if (Wire.available())
|
||||
{
|
||||
byte status = Wire.read();
|
||||
if (status & 0x1)
|
||||
{
|
||||
String log = F("INIT : Reset by WD!");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
lastBootCause = BOOT_CAUSE_EXT_WD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SPI Init
|
||||
if (Settings.InitSPI)
|
||||
{
|
||||
SPI.setHwCs(false);
|
||||
SPI.begin();
|
||||
String log = F("INIT : SPI Init (without CS)");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
else
|
||||
{
|
||||
String log = F("INIT : SPI not enabled");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
if (Settings.Pin_sd_cs > 0)
|
||||
{
|
||||
if (SD.begin(Settings.Pin_sd_cs))
|
||||
{
|
||||
String log = F("SD : Init OK");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
else
|
||||
{
|
||||
String log = F("SD : Init failed");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
* Initialize specific hardware setings (only global ones, others are set through devices)
|
||||
\*********************************************************************************************/
|
||||
|
||||
void hardwareInit()
|
||||
{
|
||||
|
||||
// set GPIO pins state if not set to default
|
||||
for (byte x=0; x < 17; x++)
|
||||
if (Settings.PinBootStates[x] != 0)
|
||||
switch(Settings.PinBootStates[x])
|
||||
{
|
||||
case 1:
|
||||
pinMode(x,OUTPUT);
|
||||
digitalWrite(x,LOW);
|
||||
setPinState(1, x, PIN_MODE_OUTPUT, LOW);
|
||||
break;
|
||||
case 2:
|
||||
pinMode(x,OUTPUT);
|
||||
digitalWrite(x,HIGH);
|
||||
setPinState(1, x, PIN_MODE_OUTPUT, HIGH);
|
||||
break;
|
||||
case 3:
|
||||
pinMode(x,INPUT_PULLUP);
|
||||
setPinState(1, x, PIN_MODE_INPUT, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// configure hardware pins according to eeprom settings.
|
||||
if (Settings.Pin_i2c_sda != -1)
|
||||
{
|
||||
String log = F("INIT : I2C");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
Wire.begin(Settings.Pin_i2c_sda, Settings.Pin_i2c_scl);
|
||||
if(Settings.WireClockStretchLimit)
|
||||
{
|
||||
String log = F("INIT : I2C custom clockstretchlimit:");
|
||||
log += Settings.WireClockStretchLimit;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
Wire.setClockStretchLimit(Settings.WireClockStretchLimit);
|
||||
}
|
||||
}
|
||||
|
||||
// I2C Watchdog boot status check
|
||||
if (Settings.WDI2CAddress != 0)
|
||||
{
|
||||
delay(500);
|
||||
Wire.beginTransmission(Settings.WDI2CAddress);
|
||||
Wire.write(0x83); // command to set pointer
|
||||
Wire.write(17); // pointer value to status byte
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(Settings.WDI2CAddress, (uint8_t)1);
|
||||
if (Wire.available())
|
||||
{
|
||||
byte status = Wire.read();
|
||||
if (status & 0x1)
|
||||
{
|
||||
String log = F("INIT : Reset by WD!");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
lastBootCause = BOOT_CAUSE_EXT_WD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SPI Init
|
||||
if (Settings.InitSPI)
|
||||
{
|
||||
SPI.setHwCs(false);
|
||||
SPI.begin();
|
||||
addLog(LOG_LEVEL_INFO, (char*)"INIT : SPI Init (without CS)");
|
||||
}
|
||||
else
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, (char*)"INIT : SPI not enabled");
|
||||
}
|
||||
}
|
||||
|
||||
+403
-478
File diff suppressed because it is too large
Load Diff
@@ -153,8 +153,7 @@ void checkUDP()
|
||||
{
|
||||
Settings.TaskDeviceNumber[infoReply.destTaskIndex] = infoReply.deviceNumber;
|
||||
Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] = 1; // remote feed
|
||||
for (byte x=0; x < CONTROLLER_MAX; x++)
|
||||
Settings.TaskDeviceSendData[x][infoReply.destTaskIndex] = false;
|
||||
Settings.TaskDeviceSendData[infoReply.destTaskIndex] = false;
|
||||
strcpy(ExtraTaskSettings.TaskDeviceName, infoReply.taskName);
|
||||
for (byte x = 0; x < VARS_PER_TASK; x++)
|
||||
strcpy( ExtraTaskSettings.TaskDeviceValueNames[x], infoReply.ValueNames[x]);
|
||||
@@ -279,7 +278,7 @@ void SendUDPCommand(byte destUnit, char* data, byte dataLength)
|
||||
firstUnit = destUnit;
|
||||
lastUnit = destUnit;
|
||||
}
|
||||
for (int x = firstUnit; x <= lastUnit; x++)
|
||||
for (byte x = firstUnit; x <= lastUnit; x++)
|
||||
{
|
||||
sendUDP(x, (byte*)data, dataLength);
|
||||
delay(10);
|
||||
@@ -293,20 +292,15 @@ void SendUDPCommand(byte destUnit, char* data, byte dataLength)
|
||||
\*********************************************************************************************/
|
||||
void sendUDP(byte unit, byte* data, byte size)
|
||||
{
|
||||
if (unit != 255)
|
||||
if (Nodes[unit].ip[0] == 0)
|
||||
return;
|
||||
if (Nodes[unit].ip[0] == 0)
|
||||
return;
|
||||
String log = "UDP : Send UDP message to ";
|
||||
log += unit;
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
|
||||
statusLED(true);
|
||||
|
||||
IPAddress remoteNodeIP;
|
||||
if (unit == 255)
|
||||
remoteNodeIP = {255,255,255,255};
|
||||
else
|
||||
remoteNodeIP = Nodes[unit].ip;
|
||||
IPAddress remoteNodeIP(Nodes[unit].ip[0], Nodes[unit].ip[1], Nodes[unit].ip[2], Nodes[unit].ip[3]);
|
||||
portUDP.beginPacket(remoteNodeIP, Settings.UDPPort);
|
||||
portUDP.write(data, size);
|
||||
portUDP.endPacket();
|
||||
@@ -344,7 +338,7 @@ void sendSysInfoUDP(byte repeats)
|
||||
// 2 byte build
|
||||
// 25 char name
|
||||
// 1 byte node type id
|
||||
|
||||
|
||||
// send my info to the world...
|
||||
strcpy_P(log, PSTR("UDP : Send Sysinfo message"));
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
@@ -388,6 +382,7 @@ void sendSysInfoUDP(byte repeats)
|
||||
}
|
||||
|
||||
|
||||
#if FEATURE_SSDP
|
||||
/********************************************************************************************\
|
||||
Respond to HTTP XML requests for SSDP information
|
||||
\*********************************************************************************************/
|
||||
@@ -429,7 +424,7 @@ void SSDP_schema(WiFiClient client) {
|
||||
ssdp_schema += F("</serialNumber>"
|
||||
"<modelName>ESP Easy</modelName>"
|
||||
"<modelNumber>");
|
||||
ssdp_schema += BUILD_GIT;
|
||||
ssdp_schema += Settings.Build;
|
||||
ssdp_schema += F("</modelNumber>"
|
||||
"<modelURL>http://www.letscontrolit.com</modelURL>"
|
||||
"<manufacturer>http://www.letscontrolit.com</manufacturer>"
|
||||
@@ -704,3 +699,5 @@ void SSDP_update() {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# ESPEasy (mega branch)
|
||||
# ESPEasy legacy branch
|
||||
|
||||
Build status: [](https://travis-ci.org/letscontrolit/ESPEasy)
|
||||
**MASTER**
|
||||
:warning:This is the ESPEasy legacy branch which isn't developed anymore.:warning:
|
||||
|
||||
This is the development branch for the next upcoming release (2.0.0). This is also known as ESPEasyMega.
|
||||
Current development branch: https://github.com/letscontrolit/ESPEasy/tree/mega (new features + fixes from v2.0 )
|
||||
|
||||
Check here to learn how to use this branch and help us improving ESPEasy: http://www.letscontrolit.com/wiki/index.php/ESPEasy#Source_code_development
|
||||
Next stable version: https://github.com/letscontrolit/ESPEasy/tree/v2.0 (fixes only)
|
||||
|
||||
Binary development releases are here: https://github.com/letscontrolit/ESPEasy/releases
|
||||
|
||||
Details and discussion are on the Experimental forum: http://www.letscontrolit.com/forum/viewtopic.php?f=18&t=2257&p=13600#p13600
|
||||
|
||||
@@ -41,4 +41,4 @@ void serial()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+654
-1000
File diff suppressed because it is too large
Load Diff
+3
-16
@@ -36,7 +36,7 @@ void WifiAPMode(boolean state)
|
||||
//********************************************************************************
|
||||
// Connect to Wifi AP
|
||||
//********************************************************************************
|
||||
boolean WifiConnect(boolean primary, byte connectAttempts)
|
||||
boolean WifiConnect(byte connectAttempts)
|
||||
{
|
||||
String log = "";
|
||||
|
||||
@@ -73,12 +73,7 @@ boolean WifiConnect(boolean primary, byte connectAttempts)
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
if (tryConnect == 1)
|
||||
{
|
||||
if (primary)
|
||||
WiFi.begin(SecuritySettings.WifiSSID, SecuritySettings.WifiKey);
|
||||
else
|
||||
WiFi.begin(SecuritySettings.WifiSSID2, SecuritySettings.WifiKey2);
|
||||
}
|
||||
WiFi.begin(SecuritySettings.WifiSSID, SecuritySettings.WifiKey);
|
||||
else
|
||||
WiFi.begin();
|
||||
|
||||
@@ -99,7 +94,6 @@ boolean WifiConnect(boolean primary, byte connectAttempts)
|
||||
sprintf_P(str, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
log += str;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
statusLED(0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -134,11 +128,6 @@ boolean WifiConnect(boolean primary, byte connectAttempts)
|
||||
WifiAPMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -200,9 +189,7 @@ void WifiCheck()
|
||||
NC_Count++;
|
||||
if (NC_Count > 2)
|
||||
{
|
||||
if (!WifiConnect(true,2))
|
||||
WifiConnect(false,2);
|
||||
|
||||
WifiConnect(2);
|
||||
C_Count=0;
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
WifiAPMode(true);
|
||||
@@ -0,0 +1,197 @@
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 001: Domoticz HTTP ######################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define CPLUGIN_001
|
||||
#define CPLUGIN_ID_001 1
|
||||
#define CPLUGIN_NAME_001 "Domoticz HTTP"
|
||||
|
||||
boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_001;
|
||||
Protocol[protocolCount].usesMQTT = false;
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 8080;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_001);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
String authHeader = "";
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0))
|
||||
{
|
||||
base64 encoder;
|
||||
String auth = SecuritySettings.ControllerUser;
|
||||
auth += ":";
|
||||
auth += SecuritySettings.ControllerPassword;
|
||||
authHeader = "Authorization: Basic " + encoder.encode(auth) + " \r\n";
|
||||
}
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return false;
|
||||
}
|
||||
statusLED(true);
|
||||
if (connectionFailures)
|
||||
connectionFailures--;
|
||||
|
||||
// We now create a URI for the request
|
||||
String url = F("/json.htm?type=command¶m=udevice&idx=");
|
||||
url += event->idx;
|
||||
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
break;
|
||||
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
|
||||
url += F("&svalue=");
|
||||
url += (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
break;
|
||||
case SENSOR_TYPE_DUAL: // any sensor that uses two simple values
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
url += ";";
|
||||
url += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM: // temp + hum + hum_stat, used for DHT11
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
url += ";";
|
||||
url += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
url += ";";
|
||||
url += humStat(UserVar[event->BaseVarIndex + 1]);
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BMP085
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
url += ";0;0;";
|
||||
url += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
url += ";0";
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
url += ";";
|
||||
url += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
url += ";";
|
||||
url += humStat(UserVar[event->BaseVarIndex + 1]);
|
||||
url += ";";
|
||||
url += toString(UserVar[event->BaseVarIndex + 2],ExtraTaskSettings.TaskDeviceValueDecimals[2]);
|
||||
url += ";0";
|
||||
break;
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
url = F("/json.htm?type=command¶m=switchlight&idx=");
|
||||
url += event->idx;
|
||||
url += F("&switchcmd=");
|
||||
if (UserVar[event->BaseVarIndex] == 0)
|
||||
url += "Off";
|
||||
else
|
||||
url += "On";
|
||||
break;
|
||||
case SENSOR_TYPE_DIMMER:
|
||||
url = F("/json.htm?type=command¶m=switchlight&idx=");
|
||||
url += event->idx;
|
||||
url += F("&switchcmd=");
|
||||
if (UserVar[event->BaseVarIndex] == 0)
|
||||
url += "Off";
|
||||
else
|
||||
{
|
||||
url += F("Set%20Level&level=");
|
||||
url += UserVar[event->BaseVarIndex];
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef PLUGIN_186
|
||||
case (SENSOR_TYPE_WIND):
|
||||
url += F("&svalue=");
|
||||
url += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
char* bearing[] = {";N;",";NNE;",";NE;",";ENE;",";E;",";ESE;",";SE;",";SSE;",";S;",";SSW;",";SW;",";WSW;",";W;",";WNW;",";NW;",";NNW;" };
|
||||
url += bearing[int(UserVar[event->BaseVarIndex] / 22.5)];
|
||||
url += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
url += ";";
|
||||
url += toString(UserVar[event->BaseVarIndex + 2],ExtraTaskSettings.TaskDeviceValueDecimals[2]);
|
||||
url += ";0";
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
url.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
|
||||
// This will send the request to the server
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + host + "\r\n" + authHeader +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && millis() < timer)
|
||||
delay(1);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Success"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
success = true;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
strcpy_P(log, PSTR("HTTP : closing connection"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int humStat(int hum){
|
||||
int lHumStat;
|
||||
if(hum<30){
|
||||
lHumStat = 2;
|
||||
}else if(hum<40){
|
||||
lHumStat = 0;
|
||||
}else if(hum<59){
|
||||
lHumStat = 1;
|
||||
}else{
|
||||
lHumStat = 3;
|
||||
|
||||
}
|
||||
return lHumStat;
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 002: Domoticz MQTT ######################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define CPLUGIN_002
|
||||
#define CPLUGIN_ID_002 2
|
||||
#define CPLUGIN_NAME_002 "Domoticz MQTT"
|
||||
|
||||
boolean CPlugin_002(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_002;
|
||||
Protocol[protocolCount].usesMQTT = true;
|
||||
Protocol[protocolCount].usesTemplate = true;
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 1883;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_002);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE:
|
||||
{
|
||||
strcpy_P(Settings.MQTTsubscribe, PSTR("domoticz/out"));
|
||||
strcpy_P(Settings.MQTTpublish, PSTR("domoticz/in"));
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_RECV:
|
||||
{
|
||||
char json[512];
|
||||
json[0] = 0;
|
||||
event->String2.toCharArray(json, 512);
|
||||
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
if (root.success())
|
||||
{
|
||||
long idx = root["idx"];
|
||||
float nvalue = root["nvalue"];
|
||||
long nvaluealt = root["nvalue"];
|
||||
//const char* name = root["name"]; // Not used
|
||||
//const char* svalue = root["svalue"]; // Not used
|
||||
const char* svalue1 = root["svalue1"];
|
||||
//const char* svalue2 = root["svalue2"]; // Not used
|
||||
//const char* svalue3 = root["svalue3"]; // Not used
|
||||
const char* switchtype = root["switchType"]; // Expect "On/Off" or "dimmer"
|
||||
if (nvalue == 0)
|
||||
nvalue = nvaluealt;
|
||||
if ((int)switchtype == 0)
|
||||
switchtype = "?";
|
||||
|
||||
for (byte x = 0; x < TASKS_MAX; x++)
|
||||
{
|
||||
if (Settings.TaskDeviceID[x] == idx)
|
||||
{
|
||||
if (Settings.TaskDeviceNumber[x] == 1) // temp solution, if input switch, update state
|
||||
{
|
||||
String action = F("inputSwitchState,");
|
||||
action += x;
|
||||
action += ",";
|
||||
action += nvalue;
|
||||
struct EventStruct TempEvent;
|
||||
parseCommandString(&TempEvent, action);
|
||||
PluginCall(PLUGIN_WRITE, &TempEvent, action);
|
||||
}
|
||||
if (Settings.TaskDeviceNumber[x] == 29) // temp solution, if plugin 029, set gpio
|
||||
{
|
||||
String action = "";
|
||||
int baseVar = x * VARS_PER_TASK;
|
||||
struct EventStruct TempEvent;
|
||||
if (strcasecmp_P(switchtype, PSTR("dimmer")) == 0)
|
||||
{
|
||||
int pwmValue = UserVar[baseVar];
|
||||
action = F("pwm,");
|
||||
action += Settings.TaskDevicePin1[x];
|
||||
action += ",";
|
||||
switch ((int)nvalue)
|
||||
{
|
||||
case 0:
|
||||
pwmValue = 0;
|
||||
break;
|
||||
case 1:
|
||||
pwmValue = UserVar[baseVar];
|
||||
break;
|
||||
case 2:
|
||||
pwmValue = 10 * atol(svalue1);
|
||||
UserVar[baseVar] = pwmValue;
|
||||
break;
|
||||
}
|
||||
action += pwmValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
UserVar[baseVar] = nvalue;
|
||||
action = F("gpio,");
|
||||
action += Settings.TaskDevicePin1[x];
|
||||
action += ",";
|
||||
action += nvalue;
|
||||
}
|
||||
parseCommandString(&TempEvent, action);
|
||||
PluginCall(PLUGIN_WRITE, &TempEvent, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
root["idx"] = event->idx;
|
||||
|
||||
String values;
|
||||
char str[80];
|
||||
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
root["nvalue"] = 0;
|
||||
values = toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
|
||||
root["nvalue"] = 0;
|
||||
values = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_DUAL: // any sensor that uses two simple values
|
||||
root["nvalue"] = 0;
|
||||
values = toString(UserVar[event->BaseVarIndex ],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
values += ";";
|
||||
values += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM: // temp + hum + hum_stat, used for DHT11
|
||||
root["nvalue"] = 0;
|
||||
values = toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
values += ";";
|
||||
values += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
values += ";0";
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BMP085
|
||||
root["nvalue"] = 0;
|
||||
values = toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
values += ";0;0;";
|
||||
values += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
values += ";0";
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
|
||||
root["nvalue"] = 0;
|
||||
values = toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
values += ";";
|
||||
values += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
values += ";0;";
|
||||
values += toString(UserVar[event->BaseVarIndex + 2],ExtraTaskSettings.TaskDeviceValueDecimals[2]);
|
||||
values += ";0";
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
root["command"] = "switchlight";
|
||||
if (UserVar[event->BaseVarIndex] == 0)
|
||||
root["switchcmd"] = "Off";
|
||||
else
|
||||
root["switchcmd"] = "On";
|
||||
break;
|
||||
case SENSOR_TYPE_DIMMER:
|
||||
root["command"] = "switchlight";
|
||||
if (UserVar[event->BaseVarIndex] == 0)
|
||||
root["switchcmd"] = "Off";
|
||||
else
|
||||
root["Set%20Level"] = UserVar[event->BaseVarIndex];
|
||||
break;
|
||||
|
||||
#ifdef PLUGIN_186
|
||||
case SENSOR_TYPE_WIND:
|
||||
values = toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
char* bearing[] = {";N;",";NNE;",";NE;",";ENE;",";E;",";ESE;",";SE;",";SSE;",";S;",";SSW;",";SW;",";WSW;",";W;",";WNW;",";NW;",";NNW;" };
|
||||
values += bearing[int(UserVar[event->BaseVarIndex] / 22.5)];
|
||||
values += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
values += ";";
|
||||
values += toString(UserVar[event->BaseVarIndex + 2],ExtraTaskSettings.TaskDeviceValueDecimals[2]);
|
||||
values += ";0;0";
|
||||
values.toCharArray(str, 80);
|
||||
root["svalue"] = str;
|
||||
break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
char json[256];
|
||||
root.printTo(json, sizeof(json));
|
||||
String log = F("MQTT : ");
|
||||
log += json;
|
||||
addLog(LOG_LEVEL_DEBUG, json);
|
||||
|
||||
String pubname = Settings.MQTTpublish;
|
||||
pubname.replace("%sysname%", Settings.Name);
|
||||
pubname.replace("%tskname%", ExtraTaskSettings.TaskDeviceName);
|
||||
pubname.replace("%id%", String(event->idx));
|
||||
|
||||
if (!MQTTclient.publish(pubname.c_str(), json, Settings.MQTTRetainFlag))
|
||||
{
|
||||
log = F("MQTT publish failed");
|
||||
addLog(LOG_LEVEL_DEBUG, json);
|
||||
MQTTConnect();
|
||||
connectionFailures++;
|
||||
}
|
||||
else if (connectionFailures)
|
||||
connectionFailures--;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -19,7 +19,6 @@ boolean CPlugin_003(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 23;
|
||||
Protocol[protocolCount].usesID = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,20 +30,17 @@ boolean CPlugin_003(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "TELNT: connecting to ", host,ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "TELNT: connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, ControllerSettings.Port))
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("TELNT: connection failed"));
|
||||
@@ -85,7 +81,7 @@ boolean CPlugin_003(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
strcpy_P(log, PSTR("TELNT: Sending pw"));
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
client.println(SecuritySettings.ControllerPassword[event->ControllerIndex]);
|
||||
client.println(SecuritySettings.ControllerPassword);
|
||||
delay(100);
|
||||
while (client.available())
|
||||
client.read();
|
||||
@@ -19,7 +19,6 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
Protocol[protocolCount].usesID = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,20 +30,17 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, ControllerSettings.Port))
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
@@ -56,7 +52,7 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
connectionFailures--;
|
||||
|
||||
String postDataStr = F("api_key=");
|
||||
postDataStr += SecuritySettings.ControllerPassword[event->ControllerIndex]; // used for API key
|
||||
postDataStr += SecuritySettings.ControllerPassword; // used for API key
|
||||
|
||||
byte valueCount = getValueCountFromSensorType(event->sensorType);
|
||||
for (byte x = 0; x < valueCount; x++)
|
||||
@@ -67,8 +63,8 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex + x],ExtraTaskSettings.TaskDeviceValueDecimals[x]);
|
||||
}
|
||||
String hostName = F("api.thingspeak.com"); // PM_CZ: HTTP requests must contain host headers.
|
||||
if (ControllerSettings.UseDNS)
|
||||
hostName = ControllerSettings.HostName;
|
||||
if (Settings.UseDNS)
|
||||
hostName = Settings.ControllerHostName;
|
||||
|
||||
String postStr = F("POST /update HTTP/1.1\r\n");
|
||||
postStr += F("Host: ");
|
||||
@@ -94,7 +90,7 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
@@ -20,7 +20,6 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 1883;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,8 +31,8 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE:
|
||||
{
|
||||
event->String1 = F("/%sysname%/#");
|
||||
event->String2 = F("/%sysname%/%tskname%/%valname%");
|
||||
strcpy_P(Settings.MQTTsubscribe, PSTR("/%sysname%/#"));
|
||||
strcpy_P(Settings.MQTTpublish, PSTR("/%sysname%/%tskname%/%valname%"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -73,28 +72,22 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
|
||||
String command = parseString(cmd, 1);
|
||||
if (command == F("event"))
|
||||
eventBuffer = cmd.substring(6);
|
||||
else if
|
||||
(PluginCall(PLUGIN_WRITE, &TempEvent, cmd));
|
||||
else
|
||||
remoteConfig(&TempEvent, cmd);
|
||||
|
||||
PluginCall(PLUGIN_WRITE, &TempEvent, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
statusLED(true);
|
||||
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0)
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String pubname = ControllerSettings.Publish;
|
||||
pubname.replace(F("%sysname%"), Settings.Name);
|
||||
pubname.replace(F("%tskname%"), ExtraTaskSettings.TaskDeviceName);
|
||||
pubname.replace(F("%id%"), String(event->idx));
|
||||
String pubname = Settings.MQTTpublish;
|
||||
pubname.replace("%sysname%", Settings.Name);
|
||||
pubname.replace("%tskname%", ExtraTaskSettings.TaskDeviceName);
|
||||
pubname.replace("%id%", String(event->idx));
|
||||
|
||||
String value = "";
|
||||
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[event->TaskIndex]);
|
||||
@@ -102,17 +95,12 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
|
||||
for (byte x = 0; x < valueCount; x++)
|
||||
{
|
||||
String tmppubname = pubname;
|
||||
tmppubname.replace(F("%valname%"), ExtraTaskSettings.TaskDeviceValueNames[x]);
|
||||
tmppubname.replace("%valname%", ExtraTaskSettings.TaskDeviceValueNames[x]);
|
||||
if (event->sensorType == SENSOR_TYPE_LONG)
|
||||
value = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
else
|
||||
value = toString(UserVar[event->BaseVarIndex + x], ExtraTaskSettings.TaskDeviceValueDecimals[x]);
|
||||
MQTTclient.publish(tmppubname.c_str(), value.c_str(), Settings.MQTTRetainFlag);
|
||||
String log = F("MQTT : ");
|
||||
log += tmppubname;
|
||||
log += " ";
|
||||
log += value;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -20,7 +20,6 @@ boolean CPlugin_006(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = false;
|
||||
Protocol[protocolCount].defaultPort = 1883;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,8 +31,8 @@ boolean CPlugin_006(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE:
|
||||
{
|
||||
event->String1 = F("/Home/#");
|
||||
event->String2 = F("/hooks/devices/%id%/SensorData/%valname%");
|
||||
strcpy_P(Settings.MQTTsubscribe, PSTR("/Home/#"));
|
||||
strcpy_P(Settings.MQTTpublish, PSTR("/hooks/devices/%id%/SensorData/%valname%"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -76,18 +75,15 @@ boolean CPlugin_006(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
statusLED(true);
|
||||
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0)
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String pubname = ControllerSettings.Publish;
|
||||
pubname.replace(F("%sysname%"), Settings.Name);
|
||||
pubname.replace(F("%tskname%"), ExtraTaskSettings.TaskDeviceName);
|
||||
pubname.replace(F("%id%"), String(event->idx));
|
||||
String pubname = Settings.MQTTpublish;
|
||||
pubname.replace("%sysname%", Settings.Name);
|
||||
pubname.replace("%tskname%", ExtraTaskSettings.TaskDeviceName);
|
||||
pubname.replace("%id%", String(event->idx));
|
||||
|
||||
String value = "";
|
||||
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[event->TaskIndex]);
|
||||
@@ -95,7 +91,7 @@ boolean CPlugin_006(byte function, struct EventStruct *event, String& string)
|
||||
for (byte x = 0; x < valueCount; x++)
|
||||
{
|
||||
String tmppubname = pubname;
|
||||
tmppubname.replace(F("%valname%"), ExtraTaskSettings.TaskDeviceValueNames[x]);
|
||||
tmppubname.replace("%valname%", ExtraTaskSettings.TaskDeviceValueNames[x]);
|
||||
if (event->sensorType == SENSOR_TYPE_LONG)
|
||||
value = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
else
|
||||
@@ -19,7 +19,6 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
Protocol[protocolCount].usesID = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,20 +30,17 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, ControllerSettings.Port))
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
@@ -102,11 +98,11 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
}
|
||||
postDataStr += F("&apikey=");
|
||||
postDataStr += SecuritySettings.ControllerPassword[event->ControllerIndex]; // "0UDNN17RW6XAS2E5" // api key
|
||||
postDataStr += SecuritySettings.ControllerPassword; // "0UDNN17RW6XAS2E5" // api key
|
||||
|
||||
String hostName = host;
|
||||
if (ControllerSettings.UseDNS)
|
||||
hostName = ControllerSettings.HostName;
|
||||
if (Settings.UseDNS)
|
||||
hostName = Settings.ControllerHostName;
|
||||
|
||||
String postStr = F(" HTTP/1.1\r\n");
|
||||
postStr += F("Host: ");
|
||||
@@ -132,7 +128,7 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
+17
-22
@@ -20,7 +20,6 @@ boolean CPlugin_008(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,8 +31,7 @@ boolean CPlugin_008(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE:
|
||||
{
|
||||
event->String1 = "";
|
||||
event->String2 = F("demo.php?name=%sysname%&task=%tskname%&valuename=%valname%&value=%value%");
|
||||
strcpy_P(Settings.MQTTpublish, PSTR("demo.php?name=%sysname%&task=%tskname%&valuename=%valname%&value=%value%"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -66,30 +64,27 @@ boolean CPlugin_008(byte function, struct EventStruct *event, String& string)
|
||||
//********************************************************************************
|
||||
boolean HTTPSend(struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
String authHeader = "";
|
||||
if ((SecuritySettings.ControllerUser[event->ControllerIndex][0] != 0) && (SecuritySettings.ControllerPassword[event->ControllerIndex][0] != 0))
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0))
|
||||
{
|
||||
base64 encoder;
|
||||
String auth = SecuritySettings.ControllerUser[event->ControllerIndex];
|
||||
String auth = SecuritySettings.ControllerUser;
|
||||
auth += ":";
|
||||
auth += SecuritySettings.ControllerPassword[event->ControllerIndex];
|
||||
auth += SecuritySettings.ControllerPassword;
|
||||
authHeader = "Authorization: Basic " + encoder.encode(auth) + " \r\n";
|
||||
}
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host, ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host, Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, ControllerSettings.Port))
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
@@ -104,22 +99,22 @@ boolean HTTPSend(struct EventStruct *event, byte varIndex, float value, unsigned
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String url = "/";
|
||||
url += ControllerSettings.Publish;
|
||||
url.replace(F("%sysname%"), URLEncode(Settings.Name));
|
||||
url.replace(F("%tskname%"), URLEncode(ExtraTaskSettings.TaskDeviceName));
|
||||
url.replace(F("%id%"), String(event->idx));
|
||||
url.replace(F("%valname%"), URLEncode(ExtraTaskSettings.TaskDeviceValueNames[varIndex]));
|
||||
url += Settings.MQTTpublish;
|
||||
url.replace("%sysname%", URLEncode(Settings.Name));
|
||||
url.replace("%tskname%", URLEncode(ExtraTaskSettings.TaskDeviceName));
|
||||
url.replace("%id%", String(event->idx));
|
||||
url.replace("%valname%", URLEncode(ExtraTaskSettings.TaskDeviceValueNames[varIndex]));
|
||||
if (longValue)
|
||||
url.replace(F("%value%"), String(longValue));
|
||||
url.replace("%value%", String(longValue));
|
||||
else
|
||||
url.replace(F("%value%"), toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]));
|
||||
url.replace("%value%", toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]));
|
||||
|
||||
url.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
|
||||
String hostName = host;
|
||||
if (ControllerSettings.UseDNS)
|
||||
hostName = ControllerSettings.HostName;
|
||||
if (Settings.UseDNS)
|
||||
hostName = Settings.ControllerHostName;
|
||||
|
||||
// This will send the request to the server
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
@@ -135,7 +130,7 @@ boolean HTTPSend(struct EventStruct *event, byte varIndex, float value, unsigned
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
+13
-17
@@ -35,7 +35,6 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesTemplate = false;
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
Protocol[protocolCount].defaultPort = 8383;
|
||||
break;
|
||||
}
|
||||
@@ -45,7 +44,7 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
string = F(CPLUGIN_NAME_009);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
|
||||
@@ -73,7 +72,7 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
// embed IP, important if there is NAT/PAT
|
||||
char ipStr[20];
|
||||
IPAddress ip = WiFi.localIP();
|
||||
sprintf_P(ipStr, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
sprintf(ipStr, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
||||
ESP["ip"] = ipStr;
|
||||
|
||||
// Create nested SENSOR json object
|
||||
@@ -116,7 +115,7 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
char buffer[root.measureLength() +1];
|
||||
root.printTo(buffer, sizeof(buffer));
|
||||
// Push data to server
|
||||
FHEMHTTPsend(url, buffer, event->ControllerIndex);
|
||||
FHEMHTTPsend(url, buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -127,19 +126,16 @@ boolean CPlugin_009(byte function, struct EventStruct *event, String& string)
|
||||
//********************************************************************************
|
||||
// FHEM HTTP request
|
||||
//********************************************************************************
|
||||
boolean FHEMHTTPsend(String url, char* buffer, byte index)
|
||||
boolean FHEMHTTPsend(String url, char* buffer)
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(index, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
boolean success = false;
|
||||
|
||||
String authHeader = "";
|
||||
if ((SecuritySettings.ControllerUser[index][0] != 0) && (SecuritySettings.ControllerPassword[index][0] != 0)) {
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0)) {
|
||||
base64 encoder;
|
||||
String auth = SecuritySettings.ControllerUser[index];
|
||||
String auth = SecuritySettings.ControllerUser;
|
||||
auth += ":";
|
||||
auth += SecuritySettings.ControllerPassword[index];
|
||||
auth += SecuritySettings.ControllerPassword;
|
||||
authHeader = "Authorization: Basic " + encoder.encode(auth) + " \r\n";
|
||||
}
|
||||
|
||||
@@ -148,14 +144,14 @@ boolean FHEMHTTPsend(String url, char* buffer, byte index)
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, ControllerSettings.Port)) {
|
||||
if (!client.connect(host, Settings.ControllerPort)) {
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
@@ -184,14 +180,14 @@ boolean FHEMHTTPsend(String url, char* buffer, byte index)
|
||||
String helper = line;
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK")) {
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK") {
|
||||
strcpy_P(log, PSTR("HTTP : Success"));
|
||||
success = true;
|
||||
}
|
||||
else if (line.substring(0, 24) == F("HTTP/1.1 400 Bad Request")) {
|
||||
else if (line.substring(0, 24) == "HTTP/1.1 400 Bad Request") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
else if (line.substring(0, 25) == F("HTTP/1.1 401 Unauthorized")) {
|
||||
else if (line.substring(0, 25) == "HTTP/1.1 401 Unauthorized") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
+12
-17
@@ -20,7 +20,6 @@ boolean CPlugin_010(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = false;
|
||||
Protocol[protocolCount].defaultPort = 514;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -32,8 +31,7 @@ boolean CPlugin_010(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case CPLUGIN_PROTOCOL_TEMPLATE:
|
||||
{
|
||||
event->String1 = "";
|
||||
event->String2 = F("%sysname%_%tskname%_%valname%=%value%");
|
||||
strcpy_P(Settings.MQTTpublish, PSTR("%sysname%_%tskname%_%valname%=%value%"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -66,15 +64,12 @@ boolean CPlugin_010(byte function, struct EventStruct *event, String& string)
|
||||
//********************************************************************************
|
||||
boolean C010_Send(struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
|
||||
{
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(event->ControllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "UDP : sending to ", host, ControllerSettings.Port);
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "UDP : sending to ", host, Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
statusLED(true);
|
||||
@@ -83,18 +78,18 @@ boolean C010_Send(struct EventStruct *event, byte varIndex, float value, unsigne
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String msg = "";
|
||||
msg += ControllerSettings.Publish;
|
||||
msg.replace(F("%sysname%"), Settings.Name);
|
||||
msg.replace(F("%tskname%"), ExtraTaskSettings.TaskDeviceName);
|
||||
msg.replace(F("%id%"), String(event->idx));
|
||||
msg.replace(F("%valname%"), ExtraTaskSettings.TaskDeviceValueNames[varIndex]);
|
||||
msg += Settings.MQTTpublish;
|
||||
msg.replace("%sysname%", Settings.Name);
|
||||
msg.replace("%tskname%", ExtraTaskSettings.TaskDeviceName);
|
||||
msg.replace("%id%", String(event->idx));
|
||||
msg.replace("%valname%", ExtraTaskSettings.TaskDeviceValueNames[varIndex]);
|
||||
if (longValue)
|
||||
msg.replace(F("%value%"), String(longValue));
|
||||
msg.replace("%value%", String(longValue));
|
||||
else
|
||||
msg.replace(F("%value%"), toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]));
|
||||
msg.replace("%value%", toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]));
|
||||
|
||||
IPAddress IP(ControllerSettings.IP[0], ControllerSettings.IP[1], ControllerSettings.IP[2], ControllerSettings.IP[3]);
|
||||
portUDP.beginPacket(IP, ControllerSettings.Port);
|
||||
IPAddress IP(Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
portUDP.beginPacket(IP, Settings.ControllerPort);
|
||||
portUDP.write(msg.c_str());
|
||||
portUDP.endPacket();
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 011: Blynk #############################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define CPLUGIN_011
|
||||
#define CPLUGIN_ID_011 11
|
||||
#define CPLUGIN_NAME_011 "Blynk HTTP [TESTING]"
|
||||
|
||||
|
||||
|
||||
|
||||
boolean CPlugin_011(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_011;
|
||||
Protocol[protocolCount].usesMQTT = false;
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 8443;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_011);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
|
||||
String postDataStr = "";
|
||||
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
Blynk_get(postDataStr );
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM: // dual value
|
||||
case SENSOR_TYPE_TEMP_BARO:
|
||||
case SENSOR_TYPE_DUAL:
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
Blynk_get(postDataStr );
|
||||
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx + 1;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
Blynk_get(postDataStr );
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO:
|
||||
case SENSOR_TYPE_TRIPLE:
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex],ExtraTaskSettings.TaskDeviceValueDecimals[0]);
|
||||
Blynk_get(postDataStr );
|
||||
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx + 1;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex + 1],ExtraTaskSettings.TaskDeviceValueDecimals[1]);
|
||||
Blynk_get(postDataStr );
|
||||
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx + 2;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += toString(UserVar[event->BaseVarIndex + 2],ExtraTaskSettings.TaskDeviceValueDecimals[2]);
|
||||
Blynk_get(postDataStr );
|
||||
|
||||
break;
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean Blynk_get(String command,float *data )
|
||||
{
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
char log[80];
|
||||
char command_char[50];
|
||||
|
||||
command.toCharArray(command_char, 50);
|
||||
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
return false;
|
||||
}
|
||||
if (connectionFailures)
|
||||
connectionFailures--;
|
||||
|
||||
// We now create a URI for the request
|
||||
char requete[300];
|
||||
sprintf_P(requete, PSTR("GET /%s/%s HTTP/1.1\r\n Host: %s \r\n Connection: close\r\n\r\n"),SecuritySettings.ControllerPassword,command_char , host );
|
||||
addLog(LOG_LEVEL_DEBUG, requete);
|
||||
client.print(requete);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && millis() < timer)
|
||||
delay(1);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
|
||||
while (client.available()) {
|
||||
|
||||
String line = client.readStringUntil('\n');
|
||||
|
||||
// success ?
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK") {
|
||||
strcpy_P(log, PSTR("HTTP : Success"));
|
||||
success = true;
|
||||
}
|
||||
else if (line.substring(0, 24) == "HTTP/1.1 400 Bad Request") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
else if (line.substring(0, 25) == "HTTP/1.1 401 Unauthorized") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// data only
|
||||
if (data && line.startsWith("["))
|
||||
{
|
||||
String strValue = line;
|
||||
byte pos = strValue.indexOf('"',2);
|
||||
strValue = strValue.substring(2, pos);
|
||||
strValue.trim();
|
||||
float value = strValue.toFloat();
|
||||
*data = value;
|
||||
success = true;
|
||||
|
||||
char value_char[5] ;
|
||||
strValue.toCharArray(value_char, 5);
|
||||
sprintf_P(log, PSTR("Blynk get - %s => %s"),command_char , value_char );
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
strcpy_P(log, PSTR("HTTP : closing connection"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
|
||||
// important - backgroudtasks - free mem
|
||||
timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 022: Pimatic RestApi ####################################
|
||||
//#######################################################################################################
|
||||
|
||||
/*******************************************************************************
|
||||
* Release notes:
|
||||
* V 1.0
|
||||
- First version by deejaybeam, 7 July 2016
|
||||
* V 1.01
|
||||
- Update and rename _C009.ino to _C022.ino by Wutu due to new standard protocols, 21 September 2016
|
||||
* V1.02
|
||||
- Remove ">210" core statement to comply (and function) with new standard 230 core as of R114, 24 September 2016
|
||||
*
|
||||
/******************************************************************************/
|
||||
|
||||
#define CPLUGIN_022
|
||||
#define CPLUGIN_ID_022 22
|
||||
#define CPLUGIN_NAME_022 "Pimatic RestApi [DEVELOPMENT]"
|
||||
|
||||
boolean CPlugin_022(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_022;
|
||||
Protocol[protocolCount].usesMQTT = false;
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_022);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
case SENSOR_TYPE_DIMMER:
|
||||
pimaticUpdateVariable(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
break;
|
||||
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
|
||||
pimaticUpdateVariable(event, 0, 0, (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16));
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM:
|
||||
case SENSOR_TYPE_TEMP_BARO:
|
||||
{
|
||||
pimaticUpdateVariable(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
unsigned long timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
pimaticUpdateVariable(event, 1, UserVar[event->BaseVarIndex + 1], 0);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO:
|
||||
{
|
||||
pimaticUpdateVariable(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
unsigned long timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
pimaticUpdateVariable(event, 1, UserVar[event->BaseVarIndex + 1], 0);
|
||||
timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
pimaticUpdateVariable(event, 2, UserVar[event->BaseVarIndex + 2], 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Pimatic updateVariable
|
||||
//********************************************************************************
|
||||
boolean pimaticUpdateVariable(struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
|
||||
{
|
||||
|
||||
String authHeader = "";
|
||||
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0))
|
||||
{
|
||||
base64 encoder;
|
||||
String auth = SecuritySettings.ControllerUser;
|
||||
auth += ":";
|
||||
auth += SecuritySettings.ControllerPassword;
|
||||
authHeader = "Authorization: Basic " + encoder.encode(auth) + " \r\n";
|
||||
}
|
||||
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host,Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return false;
|
||||
}
|
||||
statusLED(true);
|
||||
if (connectionFailures)
|
||||
connectionFailures--;
|
||||
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0)
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String url = "/api/variables/";
|
||||
url += URLEncode(ExtraTaskSettings.TaskDeviceValueNames[varIndex]);
|
||||
url.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
|
||||
String data;
|
||||
if (longValue)
|
||||
data = String(longValue);
|
||||
else
|
||||
data = toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]);
|
||||
|
||||
String yourdata = "{\"type\": \"value\", \"valueOrExpression\": \"" + data + "\"}";
|
||||
|
||||
String hostName = host;
|
||||
if (Settings.UseDNS)
|
||||
hostName = Settings.ControllerHostName;
|
||||
|
||||
// This will send the request to the server
|
||||
client.print(String("PATCH ") + url + " HTTP/1.1\r\n" +
|
||||
authHeader +
|
||||
"Host: " + hostName + "\r\n" +
|
||||
"Content-Type:application/json\r\n" +
|
||||
"Content-Length: " + yourdata.length() + "\r\n\r\n" +
|
||||
yourdata);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && millis() < timer)
|
||||
delay(1);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
success = true;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
strcpy_P(log, PSTR("HTTP : closing connection"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,239 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 025: Generic HTTP #######################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define CPLUGIN_025
|
||||
#define CPLUGIN_ID_025 25
|
||||
#define CPLUGIN_NAME_025 "Generic HTTP TEST [DEVELOPMENT]"
|
||||
|
||||
#define P025_HTTP_METHOD_MAX_LEN 16
|
||||
#define P025_HTTP_URI_MAX_LEN 240
|
||||
#define P025_HTTP_HEADER_MAX_LEN 256
|
||||
#define P025_HTTP_BODY_MAX_LEN 512
|
||||
|
||||
struct P025_ConfigStruct
|
||||
{
|
||||
char HttpMethod[P025_HTTP_METHOD_MAX_LEN];
|
||||
char HttpUri[P025_HTTP_URI_MAX_LEN];
|
||||
char HttpHeader[P025_HTTP_HEADER_MAX_LEN];
|
||||
char HttpBody[P025_HTTP_BODY_MAX_LEN];
|
||||
};
|
||||
|
||||
boolean CPlugin_025(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_025;
|
||||
Protocol[protocolCount].usesMQTT = false;
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = false;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_025);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
P025_ConfigStruct customConfig;
|
||||
LoadCustomControllerSettings((byte*)&customConfig, sizeof(customConfig));
|
||||
String methods[] = { F("GET"), F("POST"), F("PUT") };
|
||||
string += F("<TR><TD>HTTP Method :<TD><select name='P025httpmethod'>");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
string += methods[i] + "'";
|
||||
string += methods[i].equals(customConfig.HttpMethod) ? F(" selected='selected'") : F("");
|
||||
string += F(">");
|
||||
string += methods[i];
|
||||
string += F("</option>");
|
||||
}
|
||||
string += F("</select>");
|
||||
|
||||
string += F("<TR><TD>HTTP URI:<TD><input type='text' name='P025httpuri' size=80 maxlength='");
|
||||
string += P025_HTTP_URI_MAX_LEN-1;
|
||||
string += F("' value='");
|
||||
string += customConfig.HttpUri;
|
||||
string += F("'>");
|
||||
|
||||
string += F("<TR><TD>HTTP Header:<TD><textarea name='P025httpheader' rows='4' cols='50' maxlength='");
|
||||
string += P025_HTTP_HEADER_MAX_LEN-1;
|
||||
string += F("'>");
|
||||
string += customConfig.HttpHeader;
|
||||
string += F("</textarea>");
|
||||
|
||||
string += F("<TR><TD>HTTP Body:<TD><textarea name='P025httpbody' rows='8' cols='50' maxlength='");
|
||||
string += P025_HTTP_BODY_MAX_LEN-1;
|
||||
string += F("'>");
|
||||
string += customConfig.HttpBody;
|
||||
string += F("</textarea>");
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
P025_ConfigStruct customConfig;
|
||||
String httpmethod = WebServer.arg("P025httpmethod");
|
||||
String httpuri = WebServer.arg("P025httpuri");
|
||||
String httpheader = WebServer.arg("P025httpheader");
|
||||
String httpbody = WebServer.arg("P025httpbody");
|
||||
strncpy(customConfig.HttpMethod, httpmethod.c_str(), sizeof(customConfig.HttpMethod));
|
||||
strncpy(customConfig.HttpUri, httpuri.c_str(), sizeof(customConfig.HttpUri));
|
||||
strncpy(customConfig.HttpHeader, httpheader.c_str(), sizeof(customConfig.HttpHeader));
|
||||
strncpy(customConfig.HttpBody, httpbody.c_str(), sizeof(customConfig.HttpBody));
|
||||
SaveCustomControllerSettings((byte*)&customConfig, sizeof(customConfig));
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
case SENSOR_TYPE_DIMMER:
|
||||
HTTPSend025(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
break;
|
||||
case SENSOR_TYPE_LONG: // single LONG value, stored in two floats (rfid tags)
|
||||
HTTPSend025(event, 0, 0, (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16));
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM:
|
||||
case SENSOR_TYPE_TEMP_BARO:
|
||||
{
|
||||
HTTPSend025(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
unsigned long timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
HTTPSend025(event, 1, UserVar[event->BaseVarIndex + 1], 0);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO:
|
||||
{
|
||||
HTTPSend025(event, 0, UserVar[event->BaseVarIndex], 0);
|
||||
unsigned long timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
HTTPSend025(event, 1, UserVar[event->BaseVarIndex + 1], 0);
|
||||
timer = millis() + Settings.MessageDelay;
|
||||
while (millis() < timer)
|
||||
backgroundtasks();
|
||||
HTTPSend025(event, 2, UserVar[event->BaseVarIndex + 2], 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Generic HTTP get request
|
||||
//********************************************************************************
|
||||
boolean HTTPSend025(struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
|
||||
{
|
||||
P025_ConfigStruct customConfig;
|
||||
LoadCustomControllerSettings((byte*)&customConfig, sizeof(customConfig));
|
||||
|
||||
char log[80];
|
||||
boolean success = false;
|
||||
char host[20];
|
||||
sprintf_P(host, PSTR("%u.%u.%u.%u"), Settings.Controller_IP[0], Settings.Controller_IP[1], Settings.Controller_IP[2], Settings.Controller_IP[3]);
|
||||
|
||||
sprintf_P(log, PSTR("%s%s using port %u"), "HTTP : connecting to ", host, Settings.ControllerPort);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!client.connect(host, Settings.ControllerPort))
|
||||
{
|
||||
connectionFailures++;
|
||||
strcpy_P(log, PSTR("HTTP : connection failed"));
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return false;
|
||||
}
|
||||
statusLED(true);
|
||||
if (connectionFailures)
|
||||
connectionFailures--;
|
||||
|
||||
if (ExtraTaskSettings.TaskDeviceValueNames[0][0] == 0)
|
||||
PluginCall(PLUGIN_GET_DEVICEVALUENAMES, event, dummyString);
|
||||
|
||||
String hostName = host;
|
||||
if (Settings.UseDNS)
|
||||
hostName = Settings.ControllerHostName;
|
||||
|
||||
String payload = String(customConfig.HttpMethod) + " /";
|
||||
payload += customConfig.HttpUri;
|
||||
payload += String(" HTTP/1.1\r\n") +
|
||||
"Host: " + hostName + ":" + Settings.ControllerPort + "\r\n" +
|
||||
"Connection: close\r\n";
|
||||
|
||||
if (strlen(customConfig.HttpHeader) > 0)
|
||||
payload += customConfig.HttpHeader;
|
||||
ReplaceTokenByValue(payload, event, varIndex, value, longValue);
|
||||
|
||||
if (strlen(customConfig.HttpBody) > 0)
|
||||
{
|
||||
String body = String(customConfig.HttpBody);
|
||||
ReplaceTokenByValue(body, event, varIndex, value, longValue);
|
||||
payload += "\r\nContent-Length: " + String(body.length());
|
||||
payload += "\r\n\r\n" + body;
|
||||
}
|
||||
|
||||
// This will send the request to the server
|
||||
client.print(payload);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && millis() < timer)
|
||||
delay(1);
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
line.toCharArray(log, 80);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 10) == "HTTP/1.1 2")
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
success = true;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
strcpy_P(log, PSTR("HTTP : closing connection"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Replace the token in a string by real value.
|
||||
//********************************************************************************
|
||||
void ReplaceTokenByValue(String& s, struct EventStruct *event, byte varIndex, float value, unsigned long longValue)
|
||||
{
|
||||
s.replace("%sysname%", URLEncode(Settings.Name));
|
||||
s.replace("%tskname%", URLEncode(ExtraTaskSettings.TaskDeviceName));
|
||||
s.replace("%id%", String(event->idx));
|
||||
s.replace("%valname%", URLEncode(ExtraTaskSettings.TaskDeviceValueNames[varIndex]));
|
||||
if (longValue)
|
||||
s.replace("%value%", String(longValue));
|
||||
else
|
||||
s.replace("%value%", toString(value, ExtraTaskSettings.TaskDeviceValueDecimals[varIndex]));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,6 @@
|
||||
#define PLUGIN_ID_001 1
|
||||
#define PLUGIN_NAME_001 "Switch input"
|
||||
#define PLUGIN_VALUENAME1_001 "Switch"
|
||||
|
||||
boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
@@ -109,17 +108,17 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_001_type"));
|
||||
String plugin1 = WebServer.arg("plugin_001_type");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
String plugin2 = WebServer.arg(F("plugin_001_dimvalue"));
|
||||
String plugin2 = WebServer.arg("plugin_001_dimvalue");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
}
|
||||
String plugin3 = WebServer.arg(F("plugin_001_button"));
|
||||
String plugin3 = WebServer.arg("plugin_001_button");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
|
||||
|
||||
String plugin4 = WebServer.arg(F("plugin_001_boot"));
|
||||
String plugin4 = WebServer.arg("plugin_001_boot");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = (plugin4 == "on");
|
||||
|
||||
success = true;
|
||||
@@ -225,6 +224,40 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
if (command == F("rtttl"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
char sng[1024] ="";
|
||||
string.replace("-","#");
|
||||
string.toCharArray(sng, 1024);
|
||||
play_rtttl(event->Par1, sng);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
log = String(F("SW : ")) + string;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (command == F("tone"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
tone(event->Par1, event->Par2, event->Par3);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
log = String(F("SW : ")) + string;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (command == F("pwm"))
|
||||
{
|
||||
success = true;
|
||||
@@ -328,41 +361,6 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
outputstate[event->Par1] = event->Par2;
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
//play a tune via a RTTTL string, look at https://www.letscontrolit.com/forum/viewtopic.php?f=4&t=343&hilit=speaker&start=10 for more info.
|
||||
if (command == F("rtttl"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
char sng[1024] ="";
|
||||
string.replace("-","#");
|
||||
string.toCharArray(sng, 1024);
|
||||
play_rtttl(event->Par1, sng);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
log = String(F("SW : ")) + string;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
|
||||
//play a tone on pin par1, with frequency par2 and duration par3.
|
||||
if (command == F("tone"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
tone(event->Par1, event->Par2, event->Par3);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
log = String(F("SW : ")) + string;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -53,4 +53,4 @@ boolean Plugin_002(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
@@ -98,9 +98,9 @@ boolean Plugin_003(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_003"));
|
||||
String plugin1 = WebServer.arg("plugin_003");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg(F("plugin_003_countertype"));
|
||||
String plugin2 = WebServer.arg("plugin_003_countertype");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -81,7 +81,7 @@ boolean Plugin_004(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
uint8_t addr[8];
|
||||
String plugin1 = WebServer.arg(F("plugin_004_dev"));
|
||||
String plugin1 = WebServer.arg("plugin_004_dev");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
|
||||
// find the address for selected device and store into extra tasksettings
|
||||
@@ -76,7 +76,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_005_dhttype"));
|
||||
String plugin1 = WebServer.arg("plugin_005_dhttype");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -117,8 +117,7 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
dht_dat[i] = data;
|
||||
else
|
||||
{
|
||||
String log = F("DHT : protocol timeout!");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
addLog(LOG_LEVEL_ERROR, (char*)"DHT : protocol timeout!");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ boolean Plugin_006(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String elev = WebServer.arg(F("_p006_bmp085_elev"));
|
||||
String elev = WebServer.arg("_p006_bmp085_elev");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = elev.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -2,6 +2,20 @@
|
||||
//#################################### Plugin 007: ExtWiredAnalog #######################################
|
||||
//#######################################################################################################
|
||||
|
||||
/*********************************************************************************************\
|
||||
* This plugin provides support for 4 extra analog inputs, using the PCF8591 (NXP/Philips)
|
||||
* Support : www.esp8266.nu
|
||||
* Date : Apr 2015
|
||||
* Compatibility : R004
|
||||
* Syntax : "ExtWiredAnalog <Par1:Port>, <Par2:Variable>"
|
||||
*********************************************************************************************
|
||||
* Technical description:
|
||||
*
|
||||
* The PCF8591 is a IO Expander chip that connects through the I2C bus
|
||||
* Basic I2C address = 0x48
|
||||
* Each chip has 4 analog inputs
|
||||
* This commando reads the analog input and stores the result into a variable
|
||||
\*********************************************************************************************/
|
||||
#define PLUGIN_007
|
||||
#define PLUGIN_ID_007 7
|
||||
#define PLUGIN_NAME_007 "Analog input - PCF8591"
|
||||
@@ -115,4 +115,4 @@ void Plugin_008_interrupt2()
|
||||
Plugin_008_keyBuffer = Plugin_008_keyBuffer << 1; // Left shift the number (effectively multiplying by 2)
|
||||
Plugin_008_bitCount++; // Increment the bit count
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ boolean Plugin_009(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
|
||||
String plugin1 = WebServer.arg(F("plugin_009_boot"));
|
||||
String plugin1 = WebServer.arg("plugin_009_boot");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = (plugin1 == "on");
|
||||
|
||||
success = true;
|
||||
@@ -311,4 +311,4 @@ boolean Plugin_009_Config(byte Par1, byte Par2)
|
||||
Wire.endTransmission();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,29 +9,6 @@
|
||||
|
||||
#define BH1750_ADDRESS_1 0x23
|
||||
#define BH1750_ADDRESS_2 0x5c
|
||||
|
||||
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
|
||||
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10
|
||||
|
||||
// Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
|
||||
#define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11
|
||||
|
||||
// Start measurement at 4lx resolution. Measurement time is approx 16ms.
|
||||
#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13
|
||||
|
||||
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
|
||||
// Device is automatically set to Power Down after measurement.
|
||||
#define BH1750_ONE_TIME_HIGH_RES_MODE 0x20
|
||||
|
||||
// Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
|
||||
// Device is automatically set to Power Down after measurement.
|
||||
#define BH1750_ONE_TIME_HIGH_RES_MODE_2 0x21
|
||||
|
||||
// Start measurement at 1lx resolution. Measurement time is approx 120ms.
|
||||
// Device is automatically set to Power Down after measurement.
|
||||
#define BH1750_ONE_TIME_LOW_RES_MODE 0x23
|
||||
|
||||
|
||||
boolean Plugin_010_init_1 = false;
|
||||
boolean Plugin_010_init_2 = false;
|
||||
|
||||
@@ -93,45 +70,14 @@ boolean Plugin_010(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
string += F("</select>");
|
||||
|
||||
byte choiceMode = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
String optionsMode[6];
|
||||
optionsMode[0] = F("BH1750_CONTINUOUS_HIGH_RES_MODE");
|
||||
optionsMode[1] = F("BH1750_CONTINUOUS_HIGH_RES_MODE_2");
|
||||
optionsMode[2] = F("BH1750_CONTINUOUS_LOW_RES_MODE");
|
||||
optionsMode[3] = F("BH1750_ONE_TIME_HIGH_RES_MODE");
|
||||
optionsMode[4] = F("BH1750_ONE_TIME_HIGH_RES_MODE_2");
|
||||
optionsMode[5] = F("BH1750_ONE_TIME_LOW_RES_MODE");
|
||||
int optionValuesMode[6];
|
||||
optionValuesMode[0] = 0;
|
||||
optionValuesMode[1] = 1;
|
||||
optionValuesMode[2] = 2;
|
||||
optionValuesMode[3] = 3;
|
||||
optionValuesMode[4] = 4;
|
||||
optionValuesMode[5] = 5;
|
||||
string += F("<TR><TD>measurment mode:<TD><select name='plugin_010_mode'>");
|
||||
for (byte x = 0; x < 6; x++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
string += optionValuesMode[x];
|
||||
string += "'";
|
||||
if (choiceMode == optionValuesMode[x])
|
||||
string += F(" selected");
|
||||
string += ">";
|
||||
string += optionsMode[x];
|
||||
string += F("</option>");
|
||||
}
|
||||
string += F("</select>");
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_010"));
|
||||
String plugin1 = WebServer.arg("plugin_010");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg(F("plugin_010_mode"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -152,33 +98,11 @@ boolean Plugin_010(byte function, struct EventStruct *event, String& string)
|
||||
Plugin_010_init = &Plugin_010_init_2;
|
||||
}
|
||||
|
||||
byte mode = -1;
|
||||
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][1]) {
|
||||
case 0:
|
||||
mode = BH1750_CONTINUOUS_HIGH_RES_MODE;
|
||||
break;
|
||||
case 1:
|
||||
mode = BH1750_CONTINUOUS_HIGH_RES_MODE_2;
|
||||
break;
|
||||
case 2:
|
||||
mode = BH1750_CONTINUOUS_LOW_RES_MODE;
|
||||
break;
|
||||
case 3:
|
||||
mode = BH1750_ONE_TIME_HIGH_RES_MODE;
|
||||
break;
|
||||
case 4:
|
||||
mode = BH1750_ONE_TIME_HIGH_RES_MODE_2;
|
||||
break;
|
||||
case 5:
|
||||
mode = BH1750_ONE_TIME_LOW_RES_MODE;
|
||||
break;
|
||||
if (!*Plugin_010_init)
|
||||
{
|
||||
*Plugin_010_init = Plugin_010_setResolution(address);
|
||||
}
|
||||
|
||||
|
||||
*Plugin_010_init = Plugin_010_setResolution(address,mode);
|
||||
delay(150); //need this otherwise we get one wrong reading after mode change
|
||||
|
||||
|
||||
if (Wire.requestFrom(address, (uint8_t)2) == 2)
|
||||
{
|
||||
byte b1 = Wire.read();
|
||||
@@ -187,16 +111,9 @@ boolean Plugin_010(byte function, struct EventStruct *event, String& string)
|
||||
if (b1 != 0xff || b2 != 0xff) { //pm-cz: Add maximum range check
|
||||
val=((b1<<8)|b2)/1.2;
|
||||
}
|
||||
if (mode==BH1750_CONTINUOUS_HIGH_RES_MODE_2 || mode==BH1750_ONE_TIME_HIGH_RES_MODE_2) {
|
||||
UserVar[event->BaseVarIndex] = val/2;
|
||||
}
|
||||
else {
|
||||
UserVar[event->BaseVarIndex] = val;
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = val;
|
||||
String log = F("LUX 0x");
|
||||
log += String(address,HEX);
|
||||
log += F(" Mode: 0x");
|
||||
log += String(mode,HEX);
|
||||
log += F(" : Light intensity: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
@@ -208,9 +125,9 @@ boolean Plugin_010(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean Plugin_010_setResolution(uint8_t address, byte mode){
|
||||
boolean Plugin_010_setResolution(uint8_t address){
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(mode);
|
||||
Wire.write(0x10); // 1 lx resolution
|
||||
Wire.endTransmission();
|
||||
return true;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ boolean Plugin_011(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_011"));
|
||||
String plugin1 = WebServer.arg("plugin_011");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -122,11 +122,11 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_012_adr"));
|
||||
String plugin1 = WebServer.arg("plugin_012_adr");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg(F("plugin_012_size"));
|
||||
String plugin2 = WebServer.arg("plugin_012_size");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
String plugin3 = WebServer.arg(F("plugin_12_timer"));
|
||||
String plugin3 = WebServer.arg("plugin_12_timer");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
|
||||
|
||||
char deviceTemplate[4][80];
|
||||
@@ -140,6 +140,8 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
|
||||
strncpy(deviceTemplate[varNr], tmpString.c_str(), sizeof(deviceTemplate[varNr]));
|
||||
}
|
||||
|
||||
Settings.TaskDeviceID[event->TaskIndex] = 1; // temp fix, needs a dummy value
|
||||
|
||||
SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
success = true;
|
||||
break;
|
||||
@@ -251,4 +253,4 @@ boolean Plugin_012(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
@@ -86,11 +86,11 @@ boolean Plugin_013(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_013_mode"));
|
||||
String plugin1 = WebServer.arg("plugin_013_mode");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 2)
|
||||
{
|
||||
String plugin2 = WebServer.arg(F("plugin_013_threshold"));
|
||||
String plugin2 = WebServer.arg("plugin_013_threshold");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
}
|
||||
success = true;
|
||||
@@ -106,7 +106,7 @@ boolean Plugin_014(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_014_res"));
|
||||
String plugin1 = WebServer.arg("plugin_014_res");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Plugin_014_init = false; // Force device setup next time
|
||||
success = true;
|
||||
@@ -143,7 +143,7 @@ boolean Plugin_015(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_015_integration"));
|
||||
String plugin1 = WebServer.arg("plugin_015_integration");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Plugin_015_init = false; // Force device setup next time
|
||||
success = true;
|
||||
@@ -75,10 +75,6 @@ boolean Plugin_016(byte function, struct EventStruct *event, String& string)
|
||||
UserVar[event->BaseVarIndex + 1] = ((IRcode >> 16) & 0xFFFF);
|
||||
String log = F("IR : Code ");
|
||||
log += String(IRcode, HEX);
|
||||
log += F(" - Type: ");
|
||||
log += results.decode_type;
|
||||
log += F(" - Bits: ");
|
||||
log += results.bits;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
sendData(event);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ boolean Plugin_019(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
|
||||
String plugin1 = WebServer.arg(F("plugin_019_boot"));
|
||||
String plugin1 = WebServer.arg("plugin_019_boot");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = (plugin1 == "on");
|
||||
|
||||
success = true;
|
||||
@@ -7,7 +7,7 @@
|
||||
#define PLUGIN_NAME_020 "Serial Server"
|
||||
#define PLUGIN_VALUENAME1_020 "Ser2Net"
|
||||
|
||||
#define P020_BUFFER_SIZE 128
|
||||
#define BUFFER_SIZE 128
|
||||
boolean Plugin_020_init = false;
|
||||
byte Plugin_020_SerialProcessing = 0;
|
||||
|
||||
@@ -114,19 +114,19 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_020_port"));
|
||||
String plugin1 = WebServer.arg("plugin_020_port");
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg(F("plugin_020_baud"));
|
||||
String plugin2 = WebServer.arg("plugin_020_baud");
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[1] = plugin2.toInt();
|
||||
String plugin3 = WebServer.arg(F("plugin_020_data"));
|
||||
String plugin3 = WebServer.arg("plugin_020_data");
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[2] = plugin3.toInt();
|
||||
String plugin4 = WebServer.arg(F("plugin_020_parity"));
|
||||
String plugin4 = WebServer.arg("plugin_020_parity");
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[3] = plugin4.toInt();
|
||||
String plugin5 = WebServer.arg(F("plugin_020_stop"));
|
||||
String plugin5 = WebServer.arg("plugin_020_stop");
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[4] = plugin5.toInt();
|
||||
String plugin6 = WebServer.arg(F("plugin_020_rxwait"));
|
||||
String plugin6 = WebServer.arg("plugin_020_rxwait");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin6.toInt();
|
||||
String plugin7 = WebServer.arg(F("plugin_020_events"));
|
||||
String plugin7 = WebServer.arg("plugin_020_events");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin7.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -179,17 +179,17 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
if (ser2netClient.connected())
|
||||
{
|
||||
connectionState = 1;
|
||||
uint8_t net_buf[P020_BUFFER_SIZE];
|
||||
uint8_t net_buf[BUFFER_SIZE];
|
||||
int count = ser2netClient.available();
|
||||
if (count > 0)
|
||||
{
|
||||
if (count > P020_BUFFER_SIZE)
|
||||
count = P020_BUFFER_SIZE;
|
||||
if (count > BUFFER_SIZE)
|
||||
count = BUFFER_SIZE;
|
||||
bytes_read = ser2netClient.read(net_buf, count);
|
||||
Serial.write(net_buf, bytes_read);
|
||||
Serial.flush(); // Waits for the transmission of outgoing serial data to complete
|
||||
|
||||
if (count == P020_BUFFER_SIZE) // if we have a full buffer, drop the last position to stuff with string end marker
|
||||
if (count == BUFFER_SIZE) // if we have a full buffer, drop the last position to stuff with string end marker
|
||||
{
|
||||
count--;
|
||||
char log[40];
|
||||
@@ -197,7 +197,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
net_buf[count] = 0; // before logging as a char array, zero terminate the last position to be safe.
|
||||
char log[P020_BUFFER_SIZE + 40];
|
||||
char log[BUFFER_SIZE + 40];
|
||||
sprintf_P(log, PSTR("Ser2N: N>: %s"), (char*)net_buf);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
@@ -223,7 +223,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_SERIAL_IN:
|
||||
{
|
||||
uint8_t serial_buf[P020_BUFFER_SIZE];
|
||||
uint8_t serial_buf[BUFFER_SIZE];
|
||||
int RXWait = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
if (RXWait == 0)
|
||||
RXWait = 1;
|
||||
@@ -232,7 +232,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
while (timeOut > 0)
|
||||
{
|
||||
while (Serial.available()) {
|
||||
if (bytes_read < P020_BUFFER_SIZE) {
|
||||
if (bytes_read < BUFFER_SIZE) {
|
||||
serial_buf[bytes_read] = Serial.read();
|
||||
bytes_read++;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
timeOut--;
|
||||
}
|
||||
|
||||
if (bytes_read != P020_BUFFER_SIZE)
|
||||
if (bytes_read != BUFFER_SIZE)
|
||||
{
|
||||
if (bytes_read > 0) {
|
||||
if (Plugin_020_init && ser2netClient.connected())
|
||||
@@ -265,7 +265,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
serial_buf[bytes_read] = 0; // before logging as a char array, zero terminate the last position to be safe.
|
||||
char log[P020_BUFFER_SIZE + 40];
|
||||
char log[BUFFER_SIZE + 40];
|
||||
sprintf_P(log, PSTR("Ser2N: S>: %s"), (char*)serial_buf);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
@@ -295,6 +295,7 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
case 2: // RFLink
|
||||
{
|
||||
message = message.substring(6); // RFLink, strip 20;xx; from incoming message
|
||||
//message.replace("\r\n", "");
|
||||
if (message.startsWith("ESPEASY")) // Special treatment for gpio values, strip unneeded parts...
|
||||
{
|
||||
message = message.substring(8); // Strip "ESPEASY;"
|
||||
@@ -330,3 +331,4 @@ boolean Plugin_020(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -67,10 +67,10 @@ boolean Plugin_021(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_021_task"));
|
||||
String plugin2 = WebServer.arg(F("plugin_021_value"));
|
||||
String plugin3 = WebServer.arg(F("plugin_021_setvalue"));
|
||||
String plugin4 = WebServer.arg(F("plugin_021_hyst"));
|
||||
String plugin1 = WebServer.arg("plugin_021_task");
|
||||
String plugin2 = WebServer.arg("plugin_021_value");
|
||||
String plugin3 = WebServer.arg("plugin_021_setvalue");
|
||||
String plugin4 = WebServer.arg("plugin_021_hyst");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
Settings.TaskDevicePluginConfigFloat[event->TaskIndex][0] = plugin3.toFloat();
|
||||
@@ -79,22 +79,6 @@ boolean Plugin_021(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_REMOTE_CONFIG:
|
||||
{
|
||||
Serial.print("levelplugin: ");
|
||||
Serial.println(string);
|
||||
String command = parseString(string, 1);
|
||||
if (command == F("setlevel"))
|
||||
{
|
||||
String value = parseString(string, 2);
|
||||
Settings.TaskDevicePluginConfigFloat[event->TaskIndex][0] = value.toFloat();
|
||||
Serial.println(value);
|
||||
SaveSettings();
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Serial.print(F("INIT : Output "));
|
||||
@@ -7,9 +7,9 @@
|
||||
#define PLUGIN_NAME_022 "PWM - PCA9685"
|
||||
#define PLUGIN_VALUENAME1_022 "PWM"
|
||||
|
||||
#define PLUGIN_022_PCA9685_MODE1 0x00 // location for Mode1 register address
|
||||
#define PCA9685_MODE2 0x01 // location for Mode2 reigster address
|
||||
#define PCA9685_LED0 0x06 // location for start of LED0 registers
|
||||
#define PCA9685_MODE1 0x00 // location for Mode1 register address
|
||||
#define PCA9685_MODE2 0x01 // location for Mode2 reigster address
|
||||
#define PCA9685_LED0 0x06 // location for start of LED0 registers
|
||||
#define PCA9685_ADDRESS 0x40 // I2C address
|
||||
|
||||
boolean Plugin_022_init = false;
|
||||
@@ -110,10 +110,11 @@ boolean Plugin_022_Write(byte Par1, int Par2)
|
||||
|
||||
void Plugin_022_initialize()
|
||||
{
|
||||
// default mode is open drain ouput, drive leds connected to VCC
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)0x01); // reset the device
|
||||
delay(1);
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)B10100000); // set up for auto increment
|
||||
Plugin_022_writeRegister(PCA9685_MODE2, (byte)0x10); // set to output
|
||||
Plugin_022_init = true;
|
||||
// default mode is open drain ouput, drive leds connected to VCC
|
||||
Plugin_022_writeRegister(PCA9685_MODE1, (byte)0x01); // reset the device
|
||||
delay(1);
|
||||
Plugin_022_writeRegister(PCA9685_MODE1, (byte)B10100000); // set up for auto increment
|
||||
Plugin_022_writeRegister(PCA9685_MODE2, (byte)0x10); // set to output
|
||||
Plugin_022_init = true;
|
||||
}
|
||||
|
||||
@@ -149,25 +149,28 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_023_adr"));
|
||||
String plugin1 = WebServer.arg("plugin_023_adr");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg(F("plugin_023_rotate"));
|
||||
String plugin2 = WebServer.arg("plugin_023_rotate");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
String plugin3 = WebServer.arg(F("plugin_23_timer"));
|
||||
String plugin3 = WebServer.arg("plugin_23_timer");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin3.toInt();
|
||||
String plugin4 = WebServer.arg(F("plugin_023_size"));
|
||||
String plugin4 = WebServer.arg("plugin_023_size");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = plugin4.toInt();
|
||||
|
||||
char deviceTemplate[8][64];
|
||||
for (byte varNr = 0; varNr < 8; varNr++)
|
||||
{
|
||||
char argc[25];
|
||||
String arg = F("Plugin_023_template");
|
||||
arg += varNr + 1;
|
||||
String tmpString = WebServer.arg(arg);
|
||||
strncpy(deviceTemplate[varNr], tmpString.c_str(), sizeof(deviceTemplate[varNr])-1);
|
||||
deviceTemplate[varNr][63]=0;
|
||||
arg.toCharArray(argc, 25);
|
||||
String tmpString = WebServer.arg(argc);
|
||||
strncpy(deviceTemplate[varNr], tmpString.c_str(), sizeof(deviceTemplate[varNr]));
|
||||
}
|
||||
|
||||
Settings.TaskDeviceID[event->TaskIndex] = 1; // temp fix, needs a dummy value
|
||||
|
||||
SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
success = true;
|
||||
break;
|
||||
@@ -538,3 +541,4 @@ static void Plugin_023_init_OLED(void)
|
||||
Plugin_023_sendcommand(0x20); //Set Memory Addressing Mode
|
||||
Plugin_023_sendcommand(0x00); //Set Memory Addressing Mode ab Horizontal addressing mode
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ boolean Plugin_024(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_024_option"));
|
||||
String plugin1 = WebServer.arg("plugin_024_option");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Plugin_024_init = false; // Force device setup next time
|
||||
success = true;
|
||||
@@ -91,7 +91,7 @@ boolean Plugin_025(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_025_gain"));
|
||||
String plugin1 = WebServer.arg("plugin_025_gain");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Plugin_025_init = false; // Force device setup next time
|
||||
success = true;
|
||||
@@ -72,7 +72,7 @@ boolean Plugin_026(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_026"));
|
||||
String plugin1 = WebServer.arg("plugin_026");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -111,7 +111,7 @@ boolean Plugin_026(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
value = (100 - (100 * loopCounterLast / loopCounterMax));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
String log = F("SYS : ");
|
||||
@@ -129,7 +129,7 @@ boolean Plugin_027(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_027_value"));
|
||||
String plugin1 = WebServer.arg("plugin_027_value");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -151,9 +151,9 @@ boolean Plugin_028(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_028_bme280_i2c"));
|
||||
String plugin1 = WebServer.arg("plugin_028_bme280_i2c");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String elev = WebServer.arg(F("plugin_028_bme280_elev"));
|
||||
String elev = WebServer.arg("plugin_028_bme280_elev");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = elev.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -36,7 +36,6 @@ enum
|
||||
BMP280_REGISTER_TEMPDATA = 0xFA,
|
||||
|
||||
BMP280_CONTROL_SETTING = 0x57, // Oversampling: 16x P, 2x T, normal mode
|
||||
BMP280_CONFIG_SETTING = 0xE0, // Tstandby 1000ms, filter 16, 3-wire SPI Disable
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -133,9 +132,9 @@ boolean Plugin_030(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_030_bmp280_i2c"));
|
||||
String plugin1 = WebServer.arg("plugin_030_bmp280_i2c");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String elev = WebServer.arg(F("plugin_030_bmp280_elev"));
|
||||
String elev = WebServer.arg("plugin_030_bmp280_elev");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = elev.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -232,7 +231,6 @@ bool Plugin_030_begin(uint8_t a) {
|
||||
|
||||
Plugin_030_readCoefficients(a & 0x1);
|
||||
Plugin_030_write8(BMP280_REGISTER_CONTROL, BMP280_CONTROL_SETTING);
|
||||
Plugin_030_write8(BMP280_REGISTER_CONFIG, BMP280_CONFIG_SETTING);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -100,9 +100,9 @@ boolean Plugin_032(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_032_ms5611_i2c"));
|
||||
String plugin1 = WebServer.arg("plugin_032_ms5611_i2c");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String elev = WebServer.arg(F("plugin_032_ms5611_elev"));
|
||||
String elev = WebServer.arg("plugin_032_ms5611_elev");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = elev.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -85,7 +85,7 @@ boolean Plugin_033(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg(F("plugin_033_sensortype"));
|
||||
String plugin1 = WebServer.arg("plugin_033_sensortype");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 035: Output IR ############################################
|
||||
//#######################################################################################################
|
||||
|
||||
#include <IRremoteESP8266.h>
|
||||
IRsend *Plugin_035_irSender;
|
||||
|
||||
#define PLUGIN_035
|
||||
#define PLUGIN_ID_035 35
|
||||
#define PLUGIN_NAME_035 "Infrared Transmit"
|
||||
|
||||
boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_035;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].SendDataOption = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_035);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
int irPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
if (Plugin_035_irSender == 0 && irPin != -1)
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, "INIT: IR TX");
|
||||
Plugin_035_irSender = new IRsend(irPin);
|
||||
Plugin_035_irSender->begin(); // Start the sender
|
||||
}
|
||||
if (Plugin_035_irSender != 0 && irPin == -1)
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, "INIT: IR TX Removed");
|
||||
delete Plugin_035_irSender;
|
||||
Plugin_035_irSender = 0;
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
String IrType;
|
||||
unsigned long IrCode;
|
||||
unsigned int IrBits;
|
||||
char command[80];
|
||||
command[0] = 0;
|
||||
char TmpStr1[80];
|
||||
TmpStr1[0] = 0;
|
||||
string.toCharArray(command, 80);
|
||||
|
||||
String tmpString = string;
|
||||
int argIndex = tmpString.indexOf(',');
|
||||
if (argIndex) tmpString = tmpString.substring(0, argIndex);
|
||||
|
||||
if (GetArgv(command, TmpStr1, 2)) IrType = TmpStr1;
|
||||
if (GetArgv(command, TmpStr1, 3)) IrCode = strtoul(TmpStr1, NULL, 16); //(long) TmpStr1
|
||||
if (GetArgv(command, TmpStr1, 4)) IrBits = str2int(TmpStr1);
|
||||
|
||||
if (tmpString.equalsIgnoreCase("IRSEND") && Plugin_035_irSender != 0)
|
||||
{
|
||||
success = true;
|
||||
if (irReceiver != 0) irReceiver->disableIRIn(); // Stop the receiver
|
||||
|
||||
if (IrType.equalsIgnoreCase("NEC")) Plugin_035_irSender->sendNEC(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("JVC")) Plugin_035_irSender->sendJVC(IrCode, IrBits, 2);
|
||||
if (IrType.equalsIgnoreCase("RC5")) Plugin_035_irSender->sendRC5(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("RC6")) Plugin_035_irSender->sendRC6(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("SAMSUNG")) Plugin_035_irSender->sendSAMSUNG(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("SONY")) Plugin_035_irSender->sendSony(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("PANASONIC")) Plugin_035_irSender->sendPanasonic(IrBits, IrCode);
|
||||
|
||||
addLog(LOG_LEVEL_INFO, "IR Code Sent");
|
||||
if (printToWeb)
|
||||
{
|
||||
printWebString += F("IR Code Sent ");
|
||||
printWebString += IrType;
|
||||
printWebString += F("<BR>");
|
||||
}
|
||||
|
||||
if (irReceiver != 0) irReceiver->enableIRIn(); // Start the receiver
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 036: MQ2 sensors ###############################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define PLUGIN_036
|
||||
#define PLUGIN_ID_036 36
|
||||
#define PLUGIN_NAME_036 "MQ2 smoke sensor [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_036 "LPG"
|
||||
#define PLUGIN_VALUENAME2_036 "CO"
|
||||
#define PLUGIN_VALUENAME3_036 "SMOKE"
|
||||
|
||||
/************************Hardware Related Macros************************************/
|
||||
#define RL_VALUE (5) //define the load resistance on the board, in kilo ohms
|
||||
#define RO_CLEAN_AIR_FACTOR (9.83) //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
|
||||
//which is derived from the chart in datasheet
|
||||
|
||||
/***********************Software Related Macros************************************/
|
||||
#define CALIBARAION_SAMPLE_TIMES (50) //define how many samples you are going to take in the calibration phase
|
||||
#define CALIBRATION_SAMPLE_INTERVAL (500) //define the time interal(in milisecond) between each samples in the
|
||||
//cablibration phase
|
||||
#define READ_SAMPLE_INTERVAL (20) //define how many samples you are going to take in normal operation
|
||||
#define READ_SAMPLE_TIMES (5) //define the time interal(in milisecond) between each samples in
|
||||
//normal operation
|
||||
|
||||
/**********************Application Related Macros**********************************/
|
||||
#define GAS_LPG (0)
|
||||
#define GAS_CO (1)
|
||||
#define GAS_SMOKE (2)
|
||||
|
||||
/*****************************Globals***********************************************/
|
||||
float LPGCurve[3] = {2.3,0.21,-0.47}; //two points are taken from the curve.
|
||||
//with these two points, a line is formed which is "approximately equivalent"
|
||||
//to the original curve.
|
||||
//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
|
||||
float COCurve[3] = {2.3,0.72,-0.34}; //two points are taken from the curve.
|
||||
//with these two points, a line is formed which is "approximately equivalent"
|
||||
//to the original curve.
|
||||
//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000, 0.15)
|
||||
float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from the curve.
|
||||
//with these two points, a line is formed which is "approximately equivalent"
|
||||
//to the original curve.
|
||||
//data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000, -0.22)
|
||||
float Ro = 10; //Ro is initialized to 10 kilo ohms
|
||||
|
||||
|
||||
|
||||
boolean Plugin_036(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_036;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_ANALOG;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_TRIPLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 3;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_036);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_036));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_036));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_036));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
String log = F("MQ2 Calibrating...put it in fresh air");
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
Ro = MQCalibration(); //Calibrating the sensor. Please make sure the sensor is in clean air
|
||||
//when you perform the calibration
|
||||
log = F("MQ2 Calibration is done...");
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
log = F("Ro=");
|
||||
log += Ro;
|
||||
log += F("kohm");
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
//Read LPG value
|
||||
int value = MQGetGasPercentage(MQRead()/Ro,GAS_LPG);
|
||||
UserVar[event->BaseVarIndex] = (float)value;
|
||||
String log = F("MQ2 : LPG value: ");
|
||||
log += value;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
//read CO value
|
||||
value = MQGetGasPercentage(MQRead()/Ro,GAS_CO);
|
||||
UserVar[event->BaseVarIndex +1] = (float)value;
|
||||
log = F("MQ2 : CO value: ");
|
||||
log += value;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
//Read SMOKE
|
||||
value = MQGetGasPercentage(MQRead()/Ro,GAS_SMOKE);
|
||||
UserVar[event->BaseVarIndex +2] = (float)value;
|
||||
log = F("MQ2 : SMOKE value: ");
|
||||
log += value;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
//affect result
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/****************** MQResistanceCalculation ****************************************
|
||||
Input: raw_adc - raw value read from adc, which represents the voltage
|
||||
Output: the calculated sensor resistance
|
||||
Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
|
||||
across the load resistor and its resistance, the resistance of the sensor
|
||||
could be derived.
|
||||
************************************************************************************/
|
||||
float MQResistanceCalculation(int raw_adc)
|
||||
{
|
||||
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
|
||||
}
|
||||
|
||||
/***************************** MQCalibration ****************************************
|
||||
Input: mq_pin - analog channel
|
||||
Output: Ro of the sensor
|
||||
Remarks: This function assumes that the sensor is in clean air. It use
|
||||
MQResistanceCalculation to calculates the sensor resistance in clean air
|
||||
and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
|
||||
10, which differs slightly between different sensors.
|
||||
************************************************************************************/
|
||||
float MQCalibration()
|
||||
{
|
||||
int i;
|
||||
float val=0;
|
||||
|
||||
for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) { //take multiple samples
|
||||
val += MQResistanceCalculation(analogRead(A0));
|
||||
delay(CALIBRATION_SAMPLE_INTERVAL);
|
||||
}
|
||||
val = val/CALIBARAION_SAMPLE_TIMES; //calculate the average value
|
||||
|
||||
val = val/RO_CLEAN_AIR_FACTOR; //divided by RO_CLEAN_AIR_FACTOR yields the Ro
|
||||
//according to the chart in the datasheet
|
||||
|
||||
return val;
|
||||
}
|
||||
/***************************** MQRead *********************************************
|
||||
Input: mq_pin - analog channel
|
||||
Output: Rs of the sensor
|
||||
Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
|
||||
The Rs changes as the sensor is in the different consentration of the target
|
||||
gas. The sample times and the time interval between samples could be configured
|
||||
by changing the definition of the macros.
|
||||
************************************************************************************/
|
||||
float MQRead()
|
||||
{
|
||||
int i;
|
||||
float rs=0;
|
||||
|
||||
for (i=0;i<READ_SAMPLE_TIMES;i++) {
|
||||
rs += MQResistanceCalculation(analogRead(A0));
|
||||
delay(READ_SAMPLE_INTERVAL);
|
||||
}
|
||||
|
||||
rs = rs/READ_SAMPLE_TIMES;
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
/***************************** MQGetGasPercentage **********************************
|
||||
Input: rs_ro_ratio - Rs divided by Ro
|
||||
gas_id - target gas type
|
||||
Output: ppm of the target gas
|
||||
Remarks: This function passes different curves to the MQGetPercentage function which
|
||||
calculates the ppm (parts per million) of the target gas.
|
||||
************************************************************************************/
|
||||
int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
|
||||
{
|
||||
if ( gas_id == GAS_LPG ) {
|
||||
return MQGetPercentage(rs_ro_ratio,LPGCurve);
|
||||
} else if ( gas_id == GAS_CO ) {
|
||||
return MQGetPercentage(rs_ro_ratio,COCurve);
|
||||
} else if ( gas_id == GAS_SMOKE ) {
|
||||
return MQGetPercentage(rs_ro_ratio,SmokeCurve);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************** MQGetPercentage **********************************
|
||||
Input: rs_ro_ratio - Rs divided by Ro
|
||||
pcurve - pointer to the curve of the target gas
|
||||
Output: ppm of the target gas
|
||||
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
|
||||
of the line could be derived if y(rs_ro_ratio) is provided. As it is a
|
||||
logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
|
||||
value.
|
||||
************************************************************************************/
|
||||
int MQGetPercentage(float rs_ro_ratio, float *pcurve)
|
||||
{
|
||||
return (pow(10,( ((log(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################### Plugin 100 SRF01 Ultrasonic Distance Sensor ######################################
|
||||
//#######################################################################################################
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
#define PLUGIN_100
|
||||
#define PLUGIN_ID_100 100
|
||||
#define PLUGIN_NAME_100 "Ultrasonic Sensor - SRF01 [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_100 "Distance"
|
||||
|
||||
#define PLUGIN_100_srfAddress 0x01 // Address of the SFR01, default ist 0x01
|
||||
#define PLUGIN_100_getSoft 0x5D // Byte to tell SRF01 we wish to read software version
|
||||
#define PLUGIN_100_getRange 0x54 // Byte used to get range from SRF01 in cm
|
||||
#define PLUGIN_100_getStatus 0x5F // Byte used to get the status of the transducer
|
||||
|
||||
SoftwareSerial *Plugin_100_SRF;
|
||||
|
||||
uint8_t Plugin_100_SRF_Pin;
|
||||
|
||||
boolean Plugin_100(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
byte timeout;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_100;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_100);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_100));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, (char*)"INIT : SRF01");
|
||||
Plugin_100_SRF_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
Plugin_100_SRF = new SoftwareSerial(Plugin_100_SRF_Pin, Plugin_100_SRF_Pin);
|
||||
Plugin_100_SRF01_Cmd(PLUGIN_100_srfAddress, PLUGIN_100_getSoft);
|
||||
for (timeout = 0; timeout < 10; timeout++) {
|
||||
if (Plugin_100_SRF->available() < 1 ) {
|
||||
delay(10);
|
||||
} else {
|
||||
int softVer = Plugin_100_SRF->read();
|
||||
String log = F("SRF01 : Firmware-Version: ");
|
||||
log += softVer;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
return success;
|
||||
};
|
||||
};
|
||||
addLog(LOG_LEVEL_ERROR, (char*)"SRF01-Init: protocol timeout!");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
Plugin_100_SRF01_Cmd(PLUGIN_100_srfAddress, PLUGIN_100_getRange);
|
||||
for (timeout = 0; timeout < 10; timeout++) {
|
||||
if (Plugin_100_SRF->available() < 2 ) {
|
||||
delay(10);
|
||||
} else {
|
||||
byte highByte = Plugin_100_SRF->read();
|
||||
byte lowByte = Plugin_100_SRF->read();
|
||||
int dist = ((highByte << 8) + lowByte);
|
||||
UserVar[event->BaseVarIndex] = dist;
|
||||
String log = F("SRF1 : Distance: ");
|
||||
log += dist;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
return success;
|
||||
};
|
||||
};
|
||||
addLog(LOG_LEVEL_ERROR, (char*)"SRF01 : protocol timeout!");
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// Send SRF01 Command
|
||||
//**************************************************************************/
|
||||
void Plugin_100_SRF01_Cmd(byte Address, byte cmd) {
|
||||
Plugin_100_SRF->flush();
|
||||
pinMode(Plugin_100_SRF_Pin, OUTPUT);
|
||||
digitalWrite(Plugin_100_SRF_Pin, LOW);
|
||||
delay(2);
|
||||
digitalWrite(Plugin_100_SRF_Pin, HIGH);
|
||||
delay(1);
|
||||
Plugin_100_SRF->write(Address);
|
||||
Plugin_100_SRF->write(cmd);
|
||||
pinMode(Plugin_100_SRF_Pin, INPUT);
|
||||
Plugin_100_SRF->flush();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 102: Nodo Event Bridge V2 #################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define PLUGIN_102
|
||||
#define PLUGIN_ID_102 102
|
||||
#define PLUGIN_NAME_102 "Nodo Event Bridge V2 [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_102 ""
|
||||
|
||||
boolean Plugin_102(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
static byte unicastTargetUnit = 0;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_102;
|
||||
Device[deviceCount].Custom = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_102);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_102));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_UDP_IN:
|
||||
{
|
||||
// event->Data is pointer to UDP buffer
|
||||
if (event->Data[0] == 255 && event->Data[1] == 254)
|
||||
{
|
||||
if (event->Data[11] == 0) // normal traffic, Nodo flags are 0
|
||||
{
|
||||
unicastTargetUnit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unicastTargetUnit = event->Data[9]; // remote source Nodo unit will be unicast target
|
||||
}
|
||||
for (byte x = 0; x < 16; x++)
|
||||
Serial.write(event->Data[x]);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_SERIAL_IN:
|
||||
{
|
||||
if (Serial.peek() == 255)
|
||||
{
|
||||
delay(20); // wait for message to complete
|
||||
if (Serial.read() == 255 && Serial.read() == 254)
|
||||
{
|
||||
byte data[16];
|
||||
data[0] = 255;
|
||||
data[1] = 254;
|
||||
byte count = 2;
|
||||
while (Serial.available() && count < 16)
|
||||
data[count++] = Serial.read();
|
||||
|
||||
IPAddress sendIP(255, 255, 255, 255);
|
||||
|
||||
if (data[11] != 0) // flags set, set to unicast mode
|
||||
{
|
||||
if ((unicastTargetUnit != 0) && (Nodes[unicastTargetUnit].ip[0] != 0))
|
||||
for(byte x=0; x <4; x++)
|
||||
sendIP[x] = Nodes[unicastTargetUnit].ip[x];
|
||||
}
|
||||
|
||||
portUDP.beginPacket(sendIP, Settings.UDPPort);
|
||||
portUDP.write(data, 16);
|
||||
portUDP.endPacket();
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//######################### Plugin 104: SRF02 Ultrasonic range finder sensor ############################
|
||||
//#######################################################################################################
|
||||
|
||||
#define PLUGIN_104
|
||||
#define PLUGIN_ID_104 104
|
||||
#define PLUGIN_NAME_104 "Ultrasonic range finder - SRF02 [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_104 "Distance"
|
||||
|
||||
#define SRF02_ADDRESS (0x70) // default address (0x70 = datasheet address 0xE0)
|
||||
|
||||
#define SRF02_REG_COMMAND (0x00) // a read on this register returns the software revision
|
||||
#define SRF02_REG_UNUSED (0x01)
|
||||
#define SRF02_REG_RANGE_HIGH_BYTE (0x02)
|
||||
#define SRF02_REG_RANGE_LOW_BYTE (0x03)
|
||||
#define SRF02_REG_AUTOTUNE_MINIMUM_HIGH_BYTE (0x04)
|
||||
#define SRF02_REG_AUTOTUNE_MINIMUM_LOW_BYTE (0x05)
|
||||
|
||||
#define SRF02_CMD_REAL_RANGING_MODE_INCH (0x50)
|
||||
#define SRF02_CMD_REAL_RANGING_MODE_CM (0x51)
|
||||
#define SRF02_CMD_REAL_RANGING_MODE_US (0x52)
|
||||
|
||||
#define SRF02_CMD_FAKE_RANGING_MODE_INCH (0x56)
|
||||
#define SRF02_CMD_FAKE_RANGING_MODE_CM (0x57)
|
||||
#define SRF02_CMD_FAKE_RANGING_MODE_US (0x58)
|
||||
|
||||
#define SRF02_CMD_FORCE_AUTOTUNE_RESTART (0x5C)
|
||||
|
||||
#define SRF02_CMD_I2C_CHANGE_SEQ_1 (0xA0)
|
||||
#define SRF02_CMD_I2C_CHANGE_SEQ_2 (0xA5)
|
||||
#define SRF02_CMD_I2C_CHANGE_SEQ_3 (0xAA)
|
||||
|
||||
|
||||
uint8_t SRF02_i2caddr;
|
||||
|
||||
boolean Plugin_104(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_104;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_I2C;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_104);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_104));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
|
||||
String options[1];
|
||||
options[0] = F("Distance");
|
||||
|
||||
int optionValues[1];
|
||||
optionValues[0] = 0;
|
||||
|
||||
string += F("<TR><TD>Report:<TD><select name='plugin_104_value'>");
|
||||
string += F("<option value='");
|
||||
string += optionValues[0];
|
||||
string += "'";
|
||||
if (choice == optionValues[0])
|
||||
string += F(" selected");
|
||||
string += ">";
|
||||
string += options[0];
|
||||
string += F("</option>");
|
||||
string += F("</select>");
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_104_value");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_104_begin();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
float value;
|
||||
value = Plugin_104_getDistance();
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
String log = F("SRF02 : value : ");
|
||||
log += value;
|
||||
log += F("mm");
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// I2C single byte write
|
||||
//**************************************************************************/
|
||||
void Plugin_104_wireWriteByte(uint8_t reg, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(SRF02_i2caddr);
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// I2C two byte read
|
||||
//**************************************************************************/
|
||||
void Plugin_104_wireReadTwoBytes(uint8_t reg, uint16_t *value)
|
||||
{
|
||||
Wire.beginTransmission(SRF02_i2caddr);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
|
||||
delayMicroseconds(10);
|
||||
|
||||
Wire.requestFrom(SRF02_i2caddr, (uint8_t)2);
|
||||
*value = ((Wire.read() << 8) | Wire.read());
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// Sensor setup
|
||||
//**************************************************************************/
|
||||
void Plugin_104_begin(void)
|
||||
{
|
||||
SRF02_i2caddr = SRF02_ADDRESS;
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// Report distance
|
||||
//**************************************************************************/
|
||||
float Plugin_104_getDistance()
|
||||
{
|
||||
uint16_t value;
|
||||
|
||||
Plugin_104_wireWriteByte(SRF02_REG_COMMAND, SRF02_CMD_REAL_RANGING_MODE_US);
|
||||
delay(70); // transmit -> receive turnaround time (up to 65ms)
|
||||
Plugin_104_wireReadTwoBytes(SRF02_REG_RANGE_HIGH_BYTE, &value);
|
||||
|
||||
return (float)value/(float)5.82750583; // distance in [mm] (2*1000/343.2)
|
||||
}
|
||||
|
||||
#endif
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 108: WOL receiver #########################################
|
||||
//#######################################################################################################
|
||||
|
||||
// This plugin receives Wake On Lan (WOL) messages that can be used to power on a connected device.
|
||||
// Note that the ESP itself has no WOL feature. It must be active to receive this message.
|
||||
// So you can't wake an ESP from deepsleep using WOL because Wifi is down during deepsleep.
|
||||
|
||||
#define PLUGIN_108
|
||||
#define PLUGIN_ID_108 108
|
||||
#define PLUGIN_NAME_108 "WOL Receiver [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_108 "WOL"
|
||||
|
||||
WiFiUDP *WOL;
|
||||
|
||||
boolean Plugin_108(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_108;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].Custom = true;
|
||||
Device[deviceCount].TimerOption = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_108);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_108));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
string += F("<TR><TD>Power control pin:<TD>");
|
||||
addPinSelect(false, string, "taskdevicepin1", Settings.TaskDevicePin1[event->TaskIndex]);
|
||||
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
String options[2];
|
||||
options[0] = F("Active Low");
|
||||
options[1] = F("Active High");
|
||||
int optionValues[2];
|
||||
optionValues[0] = 0;
|
||||
optionValues[1] = 1;
|
||||
string += F("<TR><TD>Output state:<TD><select name='plugin_108_state'>");
|
||||
for (byte x = 0; x < 2; x++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
string += optionValues[x];
|
||||
string += "'";
|
||||
if (choice == optionValues[x])
|
||||
string += F(" selected");
|
||||
string += ">";
|
||||
string += options[x];
|
||||
string += F("</option>");
|
||||
}
|
||||
string += F("</select>");
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_108_state");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
if (!WOL)
|
||||
{
|
||||
WOL = new WiFiUDP;
|
||||
WOL->begin(7);
|
||||
}
|
||||
if (Settings.TaskDevicePin1[event->TaskIndex] != -1)
|
||||
{
|
||||
pinMode(Settings.TaskDevicePin1[event->TaskIndex], OUTPUT);
|
||||
digitalWrite(Settings.TaskDevicePin1[event->TaskIndex], !Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
|
||||
case PLUGIN_ONCE_A_SECOND:
|
||||
{
|
||||
int packetSize = WOL->parsePacket();
|
||||
if (packetSize)
|
||||
{
|
||||
statusLED(true);
|
||||
char packetBuffer[128];
|
||||
int len = WOL->read(packetBuffer, 128);
|
||||
byte match = 0;
|
||||
uint8_t mac[] = {0, 0, 0, 0, 0, 0};
|
||||
uint8_t* macread = WiFi.macAddress(mac);
|
||||
for (byte x = 0; x < 10; x++)
|
||||
if (packetBuffer[x + 6] == macread[x])
|
||||
match++;
|
||||
if (match == 6)
|
||||
{
|
||||
String log = F("WOL : Magic packet received!");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
if (Settings.TaskDevicePin1[event->TaskIndex] != -1)
|
||||
{
|
||||
String log = F("WOL : Power cycle using pin: ");
|
||||
log += Settings.TaskDevicePin1[event->TaskIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
digitalWrite(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
delay(500);
|
||||
digitalWrite(Settings.TaskDevicePin1[event->TaskIndex], !Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,260 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//################################## Plugin 109 RESOL DeltaSol Pro ######################################
|
||||
//#######################################################################################################
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
#define PLUGIN_109
|
||||
#define PLUGIN_ID_109 109
|
||||
#define PLUGIN_NAME_109 "RESOL DeltaSol Pro [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_109 "register"
|
||||
|
||||
// uart rx-buffer size
|
||||
#define RXBUF_SIZE 32
|
||||
|
||||
// RESOL register options
|
||||
#define REG_TEMP_SENSOR_1 0
|
||||
#define REG_TEMP_SENSOR_2 1
|
||||
#define REG_TEMP_SENSOR_3 2
|
||||
#define REG_RELAIS_1 3
|
||||
#define REG_RELAIS_2 4
|
||||
|
||||
// total number of selectable registers
|
||||
#define RESOL_REGISTER_OPTIONS 5
|
||||
|
||||
uint8_t Plugin_109_UART_Pin;
|
||||
boolean Plugin_109_init = false;
|
||||
boolean valuesValid = false;
|
||||
uint8_t RXbuf[RXBUF_SIZE];
|
||||
uint8_t RXbuf_IDX;
|
||||
int16_t T1, T2 ,T3;
|
||||
uint8_t R1, R2;
|
||||
|
||||
SoftwareSerial *Plugin_109_UART;
|
||||
|
||||
|
||||
// RESOL CRC check
|
||||
uint8_t VBus_CalcCrc(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
uint8_t crc;
|
||||
|
||||
crc = 0x7F;
|
||||
|
||||
for (uint8_t i = 0; i < len; i++)
|
||||
crc = (crc - buf [i]) & 0x7F;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
boolean Plugin_109(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_109;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].TimerOptional = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_109);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_109));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
int16_t choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
|
||||
String options[RESOL_REGISTER_OPTIONS];
|
||||
uint optionValues[RESOL_REGISTER_OPTIONS];
|
||||
|
||||
optionValues[0] = REG_TEMP_SENSOR_1;
|
||||
options[0] = F("Temperature sensor 1");
|
||||
optionValues[1] = REG_TEMP_SENSOR_2;
|
||||
options[1] = F("Temperature sensor 2");
|
||||
optionValues[2] = REG_TEMP_SENSOR_3;
|
||||
options[2] = F("Temperature sensor 3");
|
||||
optionValues[3] = REG_RELAIS_1;
|
||||
options[3] = F("Relais 1");
|
||||
optionValues[4] = REG_RELAIS_2;
|
||||
options[4] = F("Relais 2");
|
||||
|
||||
string += F("<TR><TD>Register:<TD><select name='plugin_109_register'>");
|
||||
for (byte x = 0; x < RESOL_REGISTER_OPTIONS; x++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
string += optionValues[x];
|
||||
string += "'";
|
||||
if (choice == optionValues[x])
|
||||
string += F(" selected");
|
||||
string += ">";
|
||||
string += options[x];
|
||||
string += F("</option>");
|
||||
}
|
||||
string += F("</select>");
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_109_register");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
Plugin_109_init = false; // Force device setup next time
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, (char*)"INIT : RESOL DeltaSol Pro");
|
||||
|
||||
Plugin_109_UART = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], false, (2 * RXBUF_SIZE)); // set RX und Tx Pin number, no invert, buffer
|
||||
|
||||
Plugin_109_init = true;
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
if (Plugin_109_init == true)
|
||||
{
|
||||
// buffer filled with more than twize the frame size bytes? -> at least one complete frame should then be available
|
||||
if (Plugin_109_UART->available() > (2 * 30))
|
||||
{
|
||||
// search for first appearance of SOF (0xAA)
|
||||
while ((Plugin_109_UART->available()) && (Plugin_109_UART->read() != 0xAA));
|
||||
|
||||
RXbuf_IDX = 0;
|
||||
RXbuf[RXbuf_IDX] = 0;
|
||||
|
||||
while ((Plugin_109_UART->available()) && (RXbuf[RXbuf_IDX] != 0xAA) && (RXbuf_IDX < (RXBUF_SIZE - 1)))
|
||||
RXbuf[++RXbuf_IDX] = Plugin_109_UART->read();
|
||||
|
||||
if (RXbuf[RXbuf_IDX] == 0xAA)
|
||||
{
|
||||
// ********* DeltaSol Pro registers *********
|
||||
|
||||
// check CRC of first and second group
|
||||
if ( (VBus_CalcCrc(&RXbuf[10], 5) == RXbuf[15]) && (VBus_CalcCrc(&RXbuf[16], 5) == RXbuf[21]) )
|
||||
{
|
||||
// Temperature sensor 1
|
||||
T1 = RXbuf[10] + ((RXbuf[14] & (1 << 0)) << 7);
|
||||
T1 += (RXbuf[11] + ((RXbuf[14] & (1 << 1)) << 6)) << 8;
|
||||
|
||||
// Temperature sensor 2
|
||||
T2 = RXbuf[12] + ((RXbuf[14] & (1 << 2)) << 5);
|
||||
T2 += (RXbuf[13] + ((RXbuf[14] & (1 << 3)) << 4)) << 8;
|
||||
|
||||
|
||||
// Temperature sensor 3
|
||||
T3 = RXbuf[16] + ((RXbuf[20] & (1 << 0)) << 7);
|
||||
T3 += (RXbuf[17] + ((RXbuf[20] & (1 << 1)) << 6)) << 8;
|
||||
|
||||
// Relais/speed
|
||||
R1 = RXbuf[18] + ((RXbuf[20] & (1 << 2)) << 5);
|
||||
R2 = RXbuf[19] + ((RXbuf[20] & (1 << 3)) << 4);
|
||||
|
||||
valuesValid = true;
|
||||
} else
|
||||
valuesValid = false;
|
||||
}
|
||||
|
||||
Plugin_109_UART->flush();
|
||||
}
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
float regValue;
|
||||
String log = F("RESOL : ");
|
||||
|
||||
if (valuesValid == true)
|
||||
{
|
||||
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
|
||||
{
|
||||
case REG_TEMP_SENSOR_1:
|
||||
{
|
||||
log += F("T1");
|
||||
regValue = (float)T1 / 10;
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_TEMP_SENSOR_2:
|
||||
{
|
||||
log += F("T2");
|
||||
regValue = (float)T2 / 10;
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_TEMP_SENSOR_3:
|
||||
{
|
||||
log += F("T3");
|
||||
regValue = (float)T3 / 10;
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_RELAIS_1:
|
||||
{
|
||||
log += F("R1");
|
||||
regValue = R1;
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_RELAIS_2:
|
||||
{
|
||||
log += F("R2");
|
||||
regValue = R2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
log += F("unknown");
|
||||
regValue = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log += F("=");
|
||||
log += regValue;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
UserVar[event->BaseVarIndex] = regValue;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//############################# Plugin 111: SenseAir CO2 Sensors ########################################
|
||||
//#######################################################################################################
|
||||
/*
|
||||
Plugin written by: Daniel Tedenljung info__AT__tedenljungconsulting.com
|
||||
|
||||
This plugin reads the co2 value of SenseAir Co2 Sensors. (S8 works, K30 is ongoing)
|
||||
Datasheet can be found here for S8: http://www.senseair.com/products/oem-modules/senseair-s8/
|
||||
Datasheet can be found here for K30: http://www.senseair.com/products/oem-modules/k30/
|
||||
|
||||
You can buy sensor from m.nu in Sweden:
|
||||
S8 https://www.m.nu/co2matare-fran-senseair-p-1440.html
|
||||
K30 https://www.m.nu/k30-co2matare-p-302.html
|
||||
*/
|
||||
|
||||
|
||||
#define PLUGIN_111
|
||||
#define PLUGIN_ID_111 111
|
||||
#define PLUGIN_NAME_111 "SenseAir CO2 Sensor [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_111 "PPM"
|
||||
|
||||
boolean Plugin_111_init = false;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial *Plugin_111_S8;
|
||||
|
||||
// 0xFE=Any address 0x04=Read input registers 0x0003=Starting address 0x0001=Number of registers to read 0xD5C5=CRC in reverse order
|
||||
byte cmdReadPPM[] = {0xFE, 0x04, 0x00, 0x03, 0x00, 0x01, 0xD5, 0xC5};
|
||||
|
||||
byte ReciveBuffer[7];
|
||||
|
||||
byte Data[5];
|
||||
byte co2[2];
|
||||
long ppm;
|
||||
|
||||
boolean Plugin_111(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_111;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_111);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_111));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_111_init = true;
|
||||
Plugin_111_S8 = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]); // TODO: Explain this in plugin description RX=GPIO Setting 1, TX=GPIO Setting 2, Use 1kOhm in serie on datapins!
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
|
||||
if (Plugin_111_init)
|
||||
{
|
||||
Plugin_111_S8->write(cmdReadPPM, sizeof(cmdReadPPM)); //Send the byte array
|
||||
delay(50);
|
||||
|
||||
// Read answer from S8
|
||||
int ByteCounter = 0;
|
||||
while (Plugin_111_S8->available()) {
|
||||
ReciveBuffer[ByteCounter] = Plugin_111_S8->read();
|
||||
ByteCounter++;
|
||||
}
|
||||
|
||||
// Divide recived chunk in different registers
|
||||
for (int i = 0 ; i < sizeof(ReciveBuffer) - 2 ; i++)
|
||||
{
|
||||
Data[i] = ReciveBuffer[i];
|
||||
}
|
||||
|
||||
co2[0] = Data[3];
|
||||
co2[1] = Data[4];
|
||||
|
||||
ppm = (co2[0] << 8) | (co2[1]);
|
||||
|
||||
int value = ppm;
|
||||
UserVar[event->BaseVarIndex] = (float)value;
|
||||
String log = F("S8 : PPM value: "); //TODO: Different string if K30 is used.
|
||||
log += value;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 112: Power Counter ########################################
|
||||
//#######################################################################################################
|
||||
//This sketch is based on Plugin 003: Pulse
|
||||
|
||||
#define PLUGIN_112
|
||||
#define PLUGIN_ID_112 112
|
||||
#define PLUGIN_NAME_112 "Power Counter [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_112 "PowerWh"
|
||||
#define PLUGIN_VALUENAME2_112 "PowerCountTotal"
|
||||
|
||||
unsigned long Plugin_112_pulseCounter[TASKS_MAX];
|
||||
unsigned long Plugin_112_pulseTotalCounter[TASKS_MAX];
|
||||
unsigned long Plugin_112_pulseTime[TASKS_MAX];
|
||||
unsigned long Plugin_112_pulseTimePrevious[TASKS_MAX];
|
||||
float Plugin_112_pulseUsage[TASKS_MAX];
|
||||
|
||||
boolean Plugin_112(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_112;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_DUAL;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 2;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_112);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_112));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_112));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
char tmpString[128];
|
||||
|
||||
sprintf_P(tmpString, PSTR("<TR><TD>Debounce Time (mSec):<TD><input type='text' name='plugin_112_debounce' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
string += tmpString;
|
||||
|
||||
sprintf_P(tmpString, PSTR("<TR><TD>Pulses per KWh:<TD><input type='text' name='plugin_112_pulsesperkwh' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
string += tmpString;
|
||||
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_112_debounce");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
String plugin2 = WebServer.arg("plugin_112_pulsesperkwh");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin2.toInt();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SHOW_VALUES:
|
||||
{
|
||||
string += ExtraTaskSettings.TaskDeviceValueNames[0];
|
||||
string += F(":");
|
||||
string += Plugin_112_pulseUsage[event->TaskIndex];
|
||||
string += F("<BR>");
|
||||
string += ExtraTaskSettings.TaskDeviceValueNames[1];
|
||||
string += F(":");
|
||||
string += Plugin_112_pulseTotalCounter[event->TaskIndex];
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
String log = F("INIT : Power Counter ");
|
||||
log += Settings.TaskDevicePin1[event->TaskIndex];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
pinMode(Settings.TaskDevicePin1[event->TaskIndex], INPUT_PULLUP);
|
||||
Plugin_112_pulseinit(Settings.TaskDevicePin1[event->TaskIndex], event->TaskIndex);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
Plugin_112_idleusage(event->TaskIndex);
|
||||
UserVar[event->BaseVarIndex] = Plugin_112_pulseUsage[event->TaskIndex];
|
||||
UserVar[event->BaseVarIndex+1] = Plugin_112_pulseTotalCounter[event->TaskIndex];
|
||||
Plugin_112_pulseCounter[event->TaskIndex] = 0;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Update usage when no pulse has been received for some time, so it will decrease on every
|
||||
* PLUGIN_READ event instead off keeping the last calculated usage value.
|
||||
\*********************************************************************************************/
|
||||
void Plugin_112_idleusage(byte Index)
|
||||
{
|
||||
unsigned long PulseTime=millis() - Plugin_112_pulseTimePrevious[Index];
|
||||
if(PulseTime > (Settings.TaskDeviceTimer[Index] * 1000) && //More than $device_delay passed since last pulse
|
||||
PulseTime > Plugin_112_pulseTime[Index] ) { //More than last pulse interval
|
||||
|
||||
// Let's prevent divison by zero
|
||||
if(Settings.TaskDevicePluginConfig[Index][1]==0) {
|
||||
Settings.TaskDevicePluginConfig[Index][1]=1000; // if not configged correctly prevent crashes and set it to 1000 as default value.
|
||||
}
|
||||
// WH = =3600000/[pulses per kwh]/[time since last pulse (ms)]
|
||||
Plugin_112_pulseUsage[Index] = (3600000000./Settings.TaskDevicePluginConfig[Index][1])/PulseTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Check Pulse Counters (called from irq handler)
|
||||
\*********************************************************************************************/
|
||||
void Plugin_112_pulsecheck(byte Index)
|
||||
{
|
||||
unsigned long PulseTime=millis() - Plugin_112_pulseTimePrevious[Index];
|
||||
if(PulseTime > Settings.TaskDevicePluginConfig[Index][0]) // check with debounce time for this task
|
||||
{
|
||||
Plugin_112_pulseTimePrevious[Index]=millis(); // moved this up as the operations below might take some time
|
||||
Plugin_112_pulseCounter[Index]++;
|
||||
Plugin_112_pulseTotalCounter[Index]++;
|
||||
Plugin_112_pulseTime[Index] = PulseTime;
|
||||
|
||||
// Let's prevent divison by zero
|
||||
if(Settings.TaskDevicePluginConfig[Index][1]==0) {
|
||||
Settings.TaskDevicePluginConfig[Index][1]=1000; // if not configged correctly prevent crashes and set it to 1000 as default value.
|
||||
}
|
||||
|
||||
// WH = =3600000/[pulses per kwh]/[time since last pulse (ms)]
|
||||
Plugin_112_pulseUsage[Index] = (3600000000./Settings.TaskDevicePluginConfig[Index][1])/PulseTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Pulse Counter IRQ handlers
|
||||
\*********************************************************************************************/
|
||||
void Plugin_112_pulse_interrupt1()
|
||||
{
|
||||
Plugin_112_pulsecheck(0);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt2()
|
||||
{
|
||||
Plugin_112_pulsecheck(1);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt3()
|
||||
{
|
||||
Plugin_112_pulsecheck(2);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt4()
|
||||
{
|
||||
Plugin_112_pulsecheck(3);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt5()
|
||||
{
|
||||
Plugin_112_pulsecheck(4);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt6()
|
||||
{
|
||||
Plugin_112_pulsecheck(5);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt7()
|
||||
{
|
||||
Plugin_112_pulsecheck(6);
|
||||
}
|
||||
void Plugin_112_pulse_interrupt8()
|
||||
{
|
||||
Plugin_112_pulsecheck(7);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Init Pulse Counters
|
||||
\*********************************************************************************************/
|
||||
void Plugin_112_pulseinit(byte Par1, byte Index)
|
||||
{
|
||||
// Init IO pins
|
||||
String log = F("Power Counter: Init");
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
|
||||
switch (Index)
|
||||
{
|
||||
case 0:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt1, FALLING);
|
||||
break;
|
||||
case 1:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt2, FALLING);
|
||||
break;
|
||||
case 2:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt3, FALLING);
|
||||
break;
|
||||
case 3:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt4, FALLING);
|
||||
break;
|
||||
case 4:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt5, FALLING);
|
||||
break;
|
||||
case 5:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt6, FALLING);
|
||||
break;
|
||||
case 6:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt7, FALLING);
|
||||
break;
|
||||
case 7:
|
||||
attachInterrupt(Par1, Plugin_112_pulse_interrupt8, FALLING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,352 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin-113: SI1145 - UV index / IR / visible ####################
|
||||
//#######################################################################################################
|
||||
//#include <Adafruit_SI1145.h>
|
||||
|
||||
#define PLUGIN_113
|
||||
#define PLUGIN_ID_113 113
|
||||
#define PLUGIN_NAME_113 "SI1145 UV index (Adafruit-QA) [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_113 "VISIBLE"
|
||||
#define PLUGIN_VALUENAME2_113 "INFRA"
|
||||
#define PLUGIN_VALUENAME3_113 "UV"
|
||||
|
||||
// ADAFRUIT SI1145 LIBRARY - Adafruit_SI1145.h
|
||||
// =============================================
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
|
||||
/* COMMANDS */
|
||||
#define SI1145_PARAM_QUERY 0x80
|
||||
#define SI1145_PARAM_SET 0xA0
|
||||
#define SI1145_NOP 0x0
|
||||
#define SI1145_RESET 0x01
|
||||
#define SI1145_BUSADDR 0x02
|
||||
#define SI1145_PS_FORCE 0x05
|
||||
#define SI1145_ALS_FORCE 0x06
|
||||
#define SI1145_PSALS_FORCE 0x07
|
||||
#define SI1145_PS_PAUSE 0x09
|
||||
#define SI1145_ALS_PAUSE 0x0A
|
||||
#define SI1145_PSALS_PAUSE 0xB
|
||||
#define SI1145_PS_AUTO 0x0D
|
||||
#define SI1145_ALS_AUTO 0x0E
|
||||
#define SI1145_PSALS_AUTO 0x0F
|
||||
#define SI1145_GET_CAL 0x12
|
||||
/* Parameters */
|
||||
#define SI1145_PARAM_I2CADDR 0x00
|
||||
#define SI1145_PARAM_CHLIST 0x01
|
||||
#define SI1145_PARAM_CHLIST_ENUV 0x80
|
||||
#define SI1145_PARAM_CHLIST_ENAUX 0x40
|
||||
#define SI1145_PARAM_CHLIST_ENALSIR 0x20
|
||||
#define SI1145_PARAM_CHLIST_ENALSVIS 0x10
|
||||
#define SI1145_PARAM_CHLIST_ENPS1 0x01
|
||||
#define SI1145_PARAM_CHLIST_ENPS2 0x02
|
||||
#define SI1145_PARAM_CHLIST_ENPS3 0x04
|
||||
#define SI1145_PARAM_PSLED12SEL 0x02
|
||||
#define SI1145_PARAM_PSLED12SEL_PS2NONE 0x00
|
||||
#define SI1145_PARAM_PSLED12SEL_PS2LED1 0x10
|
||||
#define SI1145_PARAM_PSLED12SEL_PS2LED2 0x20
|
||||
#define SI1145_PARAM_PSLED12SEL_PS2LED3 0x40
|
||||
#define SI1145_PARAM_PSLED12SEL_PS1NONE 0x00
|
||||
#define SI1145_PARAM_PSLED12SEL_PS1LED1 0x01
|
||||
#define SI1145_PARAM_PSLED12SEL_PS1LED2 0x02
|
||||
#define SI1145_PARAM_PSLED12SEL_PS1LED3 0x04
|
||||
#define SI1145_PARAM_PSLED3SEL 0x03
|
||||
#define SI1145_PARAM_PSENCODE 0x05
|
||||
#define SI1145_PARAM_ALSENCODE 0x06
|
||||
#define SI1145_PARAM_PS1ADCMUX 0x07
|
||||
#define SI1145_PARAM_PS2ADCMUX 0x08
|
||||
#define SI1145_PARAM_PS3ADCMUX 0x09
|
||||
#define SI1145_PARAM_PSADCOUNTER 0x0A
|
||||
#define SI1145_PARAM_PSADCGAIN 0x0B
|
||||
#define SI1145_PARAM_PSADCMISC 0x0C
|
||||
#define SI1145_PARAM_PSADCMISC_RANGE 0x20
|
||||
#define SI1145_PARAM_PSADCMISC_PSMODE 0x04
|
||||
#define SI1145_PARAM_ALSIRADCMUX 0x0E
|
||||
#define SI1145_PARAM_AUXADCMUX 0x0F
|
||||
#define SI1145_PARAM_ALSVISADCOUNTER 0x10
|
||||
#define SI1145_PARAM_ALSVISADCGAIN 0x11
|
||||
#define SI1145_PARAM_ALSVISADCMISC 0x12
|
||||
#define SI1145_PARAM_ALSVISADCMISC_VISRANGE 0x20
|
||||
#define SI1145_PARAM_ALSIRADCOUNTER 0x1D
|
||||
#define SI1145_PARAM_ALSIRADCGAIN 0x1E
|
||||
#define SI1145_PARAM_ALSIRADCMISC 0x1F
|
||||
#define SI1145_PARAM_ALSIRADCMISC_RANGE 0x20
|
||||
#define SI1145_PARAM_ADCCOUNTER_511CLK 0x70
|
||||
#define SI1145_PARAM_ADCMUX_SMALLIR 0x00
|
||||
#define SI1145_PARAM_ADCMUX_LARGEIR 0x03
|
||||
/* REGISTERS */
|
||||
#define SI1145_REG_PARTID 0x00
|
||||
#define SI1145_REG_REVID 0x01
|
||||
#define SI1145_REG_SEQID 0x02
|
||||
#define SI1145_REG_INTCFG 0x03
|
||||
#define SI1145_REG_INTCFG_INTOE 0x01
|
||||
#define SI1145_REG_INTCFG_INTMODE 0x02
|
||||
#define SI1145_REG_IRQEN 0x04
|
||||
#define SI1145_REG_IRQEN_ALSEVERYSAMPLE 0x01
|
||||
#define SI1145_REG_IRQEN_PS1EVERYSAMPLE 0x04
|
||||
#define SI1145_REG_IRQEN_PS2EVERYSAMPLE 0x08
|
||||
#define SI1145_REG_IRQEN_PS3EVERYSAMPLE 0x10
|
||||
#define SI1145_REG_IRQMODE1 0x05
|
||||
#define SI1145_REG_IRQMODE2 0x06
|
||||
#define SI1145_REG_HWKEY 0x07
|
||||
#define SI1145_REG_MEASRATE0 0x08
|
||||
#define SI1145_REG_MEASRATE1 0x09
|
||||
#define SI1145_REG_PSRATE 0x0A
|
||||
#define SI1145_REG_PSLED21 0x0F
|
||||
#define SI1145_REG_PSLED3 0x10
|
||||
#define SI1145_REG_UCOEFF0 0x13
|
||||
#define SI1145_REG_UCOEFF1 0x14
|
||||
#define SI1145_REG_UCOEFF2 0x15
|
||||
#define SI1145_REG_UCOEFF3 0x16
|
||||
#define SI1145_REG_PARAMWR 0x17
|
||||
#define SI1145_REG_COMMAND 0x18
|
||||
#define SI1145_REG_RESPONSE 0x20
|
||||
#define SI1145_REG_IRQSTAT 0x21
|
||||
#define SI1145_REG_IRQSTAT_ALS 0x01
|
||||
#define SI1145_REG_ALSVISDATA0 0x22
|
||||
#define SI1145_REG_ALSVISDATA1 0x23
|
||||
#define SI1145_REG_ALSIRDATA0 0x24
|
||||
#define SI1145_REG_ALSIRDATA1 0x25
|
||||
#define SI1145_REG_PS1DATA0 0x26
|
||||
#define SI1145_REG_PS1DATA1 0x27
|
||||
#define SI1145_REG_PS2DATA0 0x28
|
||||
#define SI1145_REG_PS2DATA1 0x29
|
||||
#define SI1145_REG_PS3DATA0 0x2A
|
||||
#define SI1145_REG_PS3DATA1 0x2B
|
||||
#define SI1145_REG_UVINDEX0 0x2C
|
||||
#define SI1145_REG_UVINDEX1 0x2D
|
||||
#define SI1145_REG_PARAMRD 0x2E
|
||||
#define SI1145_REG_CHIPSTAT 0x30
|
||||
#define SI1145_ADDR 0x60
|
||||
|
||||
class Adafruit_SI1145 {
|
||||
public:
|
||||
Adafruit_SI1145(void);
|
||||
boolean begin();
|
||||
void reset();
|
||||
uint16_t readUV();
|
||||
uint16_t readIR();
|
||||
uint16_t readVisible();
|
||||
uint16_t readProx();
|
||||
private:
|
||||
uint16_t read16(uint8_t addr);
|
||||
uint8_t read8(uint8_t addr);
|
||||
void write8(uint8_t reg, uint8_t val);
|
||||
uint8_t readParam(uint8_t p);
|
||||
uint8_t writeParam(uint8_t p, uint8_t v);
|
||||
uint8_t _addr;
|
||||
};
|
||||
|
||||
// ADAFRUIT SI1145 LIBRARY - Adafruit_SI1145.cpp
|
||||
// =============================================
|
||||
Adafruit_SI1145::Adafruit_SI1145() {
|
||||
_addr = SI1145_ADDR;
|
||||
}
|
||||
|
||||
boolean Adafruit_SI1145::begin(void) {
|
||||
Wire.begin();
|
||||
uint8_t id = read8(SI1145_REG_PARTID);
|
||||
if (id != 0x45) return false; // look for SI1145
|
||||
reset();
|
||||
/***********************************/
|
||||
// enable UVindex measurement coefficients!
|
||||
write8(SI1145_REG_UCOEFF0, 0x29);
|
||||
write8(SI1145_REG_UCOEFF1, 0x89);
|
||||
write8(SI1145_REG_UCOEFF2, 0x02);
|
||||
write8(SI1145_REG_UCOEFF3, 0x00);
|
||||
// enable UV sensor
|
||||
writeParam(SI1145_PARAM_CHLIST, SI1145_PARAM_CHLIST_ENUV |
|
||||
SI1145_PARAM_CHLIST_ENALSIR | SI1145_PARAM_CHLIST_ENALSVIS |
|
||||
SI1145_PARAM_CHLIST_ENPS1);
|
||||
// enable interrupt on every sample
|
||||
write8(SI1145_REG_INTCFG, SI1145_REG_INTCFG_INTOE);
|
||||
write8(SI1145_REG_IRQEN, SI1145_REG_IRQEN_ALSEVERYSAMPLE);
|
||||
/****************************** Prox Sense 1 */
|
||||
// program LED current
|
||||
write8(SI1145_REG_PSLED21, 0x03); // 20mA for LED 1 only
|
||||
writeParam(SI1145_PARAM_PS1ADCMUX, SI1145_PARAM_ADCMUX_LARGEIR);
|
||||
// prox sensor #1 uses LED #1
|
||||
writeParam(SI1145_PARAM_PSLED12SEL, SI1145_PARAM_PSLED12SEL_PS1LED1);
|
||||
// fastest clocks, clock div 1
|
||||
writeParam(SI1145_PARAM_PSADCGAIN, 0);
|
||||
// take 511 clocks to measure
|
||||
writeParam(SI1145_PARAM_PSADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
|
||||
// in prox mode, high range
|
||||
writeParam(SI1145_PARAM_PSADCMISC, SI1145_PARAM_PSADCMISC_RANGE|
|
||||
SI1145_PARAM_PSADCMISC_PSMODE);
|
||||
writeParam(SI1145_PARAM_ALSIRADCMUX, SI1145_PARAM_ADCMUX_SMALLIR);
|
||||
// fastest clocks, clock div 1
|
||||
writeParam(SI1145_PARAM_ALSIRADCGAIN, 0);
|
||||
// take 511 clocks to measure
|
||||
writeParam(SI1145_PARAM_ALSIRADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
|
||||
// in high range mode
|
||||
writeParam(SI1145_PARAM_ALSIRADCMISC, SI1145_PARAM_ALSIRADCMISC_RANGE);
|
||||
// fastest clocks, clock div 1
|
||||
writeParam(SI1145_PARAM_ALSVISADCGAIN, 0);
|
||||
// take 511 clocks to measure
|
||||
writeParam(SI1145_PARAM_ALSVISADCOUNTER, SI1145_PARAM_ADCCOUNTER_511CLK);
|
||||
// in high range mode (not normal signal)
|
||||
writeParam(SI1145_PARAM_ALSVISADCMISC, SI1145_PARAM_ALSVISADCMISC_VISRANGE);
|
||||
/************************/
|
||||
// measurement rate for auto
|
||||
write8(SI1145_REG_MEASRATE0, 0xFF); // 255 * 31.25uS = 8ms
|
||||
// auto run
|
||||
write8(SI1145_REG_COMMAND, SI1145_PSALS_AUTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Adafruit_SI1145::reset() {
|
||||
write8(SI1145_REG_MEASRATE0, 0);
|
||||
write8(SI1145_REG_MEASRATE1, 0);
|
||||
write8(SI1145_REG_IRQEN, 0);
|
||||
write8(SI1145_REG_IRQMODE1, 0);
|
||||
write8(SI1145_REG_IRQMODE2, 0);
|
||||
write8(SI1145_REG_INTCFG, 0);
|
||||
write8(SI1145_REG_IRQSTAT, 0xFF);
|
||||
write8(SI1145_REG_COMMAND, SI1145_RESET);
|
||||
delay(10);
|
||||
write8(SI1145_REG_HWKEY, 0x17);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// returns the UV index * 100 (divide by 100 to get the index)
|
||||
uint16_t Adafruit_SI1145::readUV(void) { return read16(0x2C); }
|
||||
// returns visible+IR light levels
|
||||
uint16_t Adafruit_SI1145::readVisible(void) { return read16(0x22); }
|
||||
// returns IR light levels
|
||||
uint16_t Adafruit_SI1145::readIR(void) { return read16(0x24); }
|
||||
|
||||
// returns "Proximity" - assumes an IR LED is attached to LED
|
||||
uint16_t Adafruit_SI1145::readProx(void) {
|
||||
return read16(0x26);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
uint8_t Adafruit_SI1145::writeParam(uint8_t p, uint8_t v) {
|
||||
//Serial.print("Param 0x"); Serial.print(p, HEX);
|
||||
//Serial.print(" = 0x"); Serial.println(v, HEX);
|
||||
write8(SI1145_REG_PARAMWR, v);
|
||||
write8(SI1145_REG_COMMAND, p | SI1145_PARAM_SET);
|
||||
return read8(SI1145_REG_PARAMRD);
|
||||
}
|
||||
|
||||
uint8_t Adafruit_SI1145::readParam(uint8_t p) {
|
||||
write8(SI1145_REG_COMMAND, p | SI1145_PARAM_QUERY);
|
||||
return read8(SI1145_REG_PARAMRD);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
uint8_t Adafruit_SI1145::read8(uint8_t reg) {
|
||||
uint16_t val;
|
||||
Wire.beginTransmission(_addr);
|
||||
Wire.write((uint8_t)reg);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom((uint8_t)_addr, (uint8_t)1);
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
uint16_t Adafruit_SI1145::read16(uint8_t a) {
|
||||
uint16_t ret;
|
||||
Wire.beginTransmission(_addr); // start transmission to device
|
||||
Wire.write(a); // sends register address to read from
|
||||
Wire.endTransmission(); // end transmission
|
||||
Wire.requestFrom(_addr, (uint8_t)2);// send data n-bytes read
|
||||
ret = Wire.read(); // receive DATA
|
||||
ret |= (uint16_t)Wire.read() << 8; // receive DATA
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Adafruit_SI1145::write8(uint8_t reg, uint8_t val) {
|
||||
Wire.beginTransmission(_addr); // start transmission to device
|
||||
Wire.write(reg); // sends register address to write
|
||||
Wire.write(val); // sends value
|
||||
Wire.endTransmission(); // end transmission
|
||||
}
|
||||
|
||||
Adafruit_SI1145 uv = Adafruit_SI1145();
|
||||
|
||||
boolean Plugin_113_init = false;
|
||||
|
||||
boolean Plugin_113(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success=false;
|
||||
|
||||
switch(function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_113;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_I2C;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 3;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_113);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_113));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_113));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_113));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
if (!Plugin_113_init)
|
||||
{
|
||||
// ziadnu EXTRA inicializaciu netreba ...
|
||||
if (uv.begin()) { Plugin_113_init = true; }
|
||||
}
|
||||
float si1145_vis = 0.0;
|
||||
float si1145_ir = 0.0;
|
||||
float si1145_uv = 0.0;
|
||||
si1145_vis = uv.readVisible();
|
||||
si1145_ir = uv.readIR();
|
||||
si1145_uv = uv.readUV();
|
||||
si1145_uv /= 100.0;
|
||||
|
||||
UserVar[event->BaseVarIndex] = si1145_vis;
|
||||
UserVar[event->BaseVarIndex+1] = si1145_ir;
|
||||
UserVar[event->BaseVarIndex+2] = si1145_uv;
|
||||
|
||||
String log = F("SI1145: Visible: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
log = F("SI1145: Infrared: ");
|
||||
log += UserVar[event->BaseVarIndex+1];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
log = F("SI1145: UV index: ");
|
||||
log += UserVar[event->BaseVarIndex+2];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
success=true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,178 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 114: DMS501A #############################################
|
||||
//#################################### by serpa #############################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define PLUGIN_114
|
||||
#define PLUGIN_ID_114 114
|
||||
#define PLUGIN_NAME_114 "Dust sensor - DSM501a [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_114 "PM1.0" // from the datasheet the detection is from PM1 and up. You could have from PM1 to PM2.5, on subtracting PM2.5 value on PM1 value. This value come from the pin #4
|
||||
#define PLUGIN_VALUENAME2_114 "PM2.5" // from the datasheet the detection is from PM2.5 and up. This value come from the pin #2. With different resistor topn the pin #1, you could adjust the size threshold detection
|
||||
|
||||
unsigned long Plugin_114_pulseCounter[TASKS_MAX];
|
||||
unsigned long Plugin_114_pulseTotalCounter[TASKS_MAX];
|
||||
unsigned long Plugin_114_pulseTime[TASKS_MAX];
|
||||
unsigned long Plugin_114_pulseTimePrevious[TASKS_MAX];
|
||||
unsigned long tstart1, tstart2;
|
||||
unsigned long tduration = 30000; // duration of measurement in ms
|
||||
//unsigned long triggerOn; // start of pulse time in us
|
||||
//unsigned long triggerOff; // end of pulse time in us
|
||||
//unsigned long lowpulseoccupancy; // duration of pulse in us
|
||||
volatile unsigned long thigh1, thigh2;
|
||||
volatile unsigned long tlow1, tlow2;
|
||||
volatile unsigned long startlow1, startlow2;
|
||||
volatile unsigned long starthigh1, starthigh2;
|
||||
volatile boolean done1, done2;
|
||||
volatile boolean value1, value2;
|
||||
//boolean trigger = false;
|
||||
volatile float ratio1, ratio2;
|
||||
volatile int DMSpin1, DMSpin2;
|
||||
float dens1, dens2;
|
||||
boolean Plugin_114(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_114;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_TEMP_HUM;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 2;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_114);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_114));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_114));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
char tmpString[128];
|
||||
sprintf_P(tmpString, PSTR("<TR><TD>Averaging Time (mSec):<TD><input type='text' name='plugin_114' value='%u'>"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
string += tmpString;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_114");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
// tduration= Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
String log = F("INIT : DSM501A ");
|
||||
log += Settings.TaskDevicePin1[event->TaskIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
// tduration= Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
tstart1 = millis();
|
||||
startlow1 = micros();
|
||||
starthigh1 = startlow1;
|
||||
DMSpin1 = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
pinMode(DMSpin1, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(DMSpin1), Plugin_114_ISR1, CHANGE);
|
||||
tstart2 = millis();
|
||||
startlow2 = micros();
|
||||
starthigh2 = startlow2;
|
||||
DMSpin2 = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
pinMode(DMSpin2, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(DMSpin2), Plugin_114_ISR2, CHANGE);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
if (done1 && done2) {
|
||||
done1 = FALSE;
|
||||
dens1 = ratio1 * 110; // ug/m^3
|
||||
done2 = FALSE;
|
||||
dens2 = ratio2 * 110; // ug/m^3
|
||||
|
||||
String log = F("DSM501A: PM1.0=");
|
||||
log += dens1;
|
||||
log += F(" PM2.5=");
|
||||
log += dens2;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
UserVar[event->BaseVarIndex] = (float) dens1;
|
||||
UserVar[event->BaseVarIndex + 1] = (float) dens2;
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
Check Pulse (called from irq handler)
|
||||
\*********************************************************************************************/
|
||||
void Plugin_114_ISR1()
|
||||
{
|
||||
value1 = digitalRead(DMSpin1); //read input pin just changed
|
||||
if (value1 == 0) { // gone low
|
||||
startlow1 = micros(); // record starting of low period
|
||||
thigh1 += startlow1 - starthigh1; // record duration of past high state
|
||||
} else { // gone high
|
||||
starthigh1 = micros(); // record starting of high period
|
||||
tlow1 += starthigh1 - startlow1; // record duration of past low state
|
||||
}
|
||||
if (millis() > tstart1 + tduration) { // check if average time has past
|
||||
tstart1 = millis(); // reset time period
|
||||
ratio1 = float(tlow1) / float(thigh1 + tlow1) * 100; // compute ratio low to total
|
||||
tlow1 = 0; // reset low time counter
|
||||
thigh1 = 0; // reset high time counter
|
||||
done1 = TRUE; // set reading complete flag
|
||||
}
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
Check Pulse (called from irq handler)
|
||||
\*********************************************************************************************/
|
||||
void Plugin_114_ISR2()
|
||||
{
|
||||
value2 = digitalRead(DMSpin2); //read input pin just changed
|
||||
if (value2 == 0) { // gone low
|
||||
startlow2 = micros(); // record starting of low period
|
||||
thigh2 += startlow2 - starthigh2; // record duration of past high state
|
||||
} else { // gone high
|
||||
starthigh2 = micros(); // record starting of high period
|
||||
tlow2 += starthigh2 - startlow2; // record duration of past low state
|
||||
}
|
||||
if (millis() > tstart2 + tduration) { // check if average time has past
|
||||
tstart2 = millis(); // reset time period
|
||||
ratio2 = float(tlow2) / float(thigh2 + tlow2) * 100; // compute ratio low to high
|
||||
tlow2 = 0; // reset low time counter
|
||||
thigh2 = 0; // reset high time counter
|
||||
done2 = TRUE; // set reading complete flag
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
@@ -1,15 +1,17 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 040: Serial RFID ID-12 ####################################
|
||||
//#################################### Plugin 116: Serial RFID ID-12 ####################################
|
||||
//#######################################################################################################
|
||||
|
||||
#define PLUGIN_040
|
||||
#define PLUGIN_ID_040 40
|
||||
#define PLUGIN_NAME_040 "RFID Reader - ID12LA/RDM6300"
|
||||
#define PLUGIN_VALUENAME1_040 "Tag"
|
||||
#define PLUGIN_116
|
||||
#define PLUGIN_ID_116 116
|
||||
#define PLUGIN_NAME_116 "RFID Reader - ID12LA [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_116 "Tag"
|
||||
|
||||
boolean Plugin_040_init = false;
|
||||
boolean Plugin_116_init = false;
|
||||
|
||||
boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_116(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
@@ -18,7 +20,7 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_040;
|
||||
Device[++deviceCount].Number = PLUGIN_ID_116;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_LONG;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
@@ -33,20 +35,20 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_040);
|
||||
string = F(PLUGIN_NAME_116);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_040));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_116));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_040_init = true;
|
||||
Plugin_116_init = true;
|
||||
Serial.begin(9600);
|
||||
success = true;
|
||||
break;
|
||||
@@ -55,7 +57,7 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_SERIAL_IN:
|
||||
{
|
||||
if (Plugin_040_init)
|
||||
if (Plugin_116_init)
|
||||
{
|
||||
byte val = 0;
|
||||
byte code[6];
|
||||
@@ -107,11 +109,12 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
// temp woraround, ESP Easy framework does not currently prepare this...
|
||||
byte index = 0;
|
||||
for (byte y = 0; y < TASKS_MAX; y++)
|
||||
if (Settings.TaskDeviceNumber[y] == PLUGIN_ID_040)
|
||||
if (Settings.TaskDeviceNumber[y] == PLUGIN_ID_116)
|
||||
index = y;
|
||||
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[index]);
|
||||
event->TaskIndex = index;
|
||||
event->BaseVarIndex = index * VARS_PER_TASK;
|
||||
event->idx = Settings.TaskDeviceID[index];
|
||||
event->sensorType = Device[DeviceIndex].VType;
|
||||
// endof workaround
|
||||
|
||||
@@ -134,3 +137,4 @@ boolean Plugin_040(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 045: MPU6050 [Testing] ####################################
|
||||
//#################################### Plugin 118: MPU6050 [Testing] ####################################
|
||||
//#######################################################################################################
|
||||
|
||||
// Based on the works of Nolan Gilley @ https://home-assistant.io/blog/2016/08/03/laundry-automation-update/
|
||||
@@ -34,14 +34,13 @@
|
||||
// detection function to setup the plugin for further use.
|
||||
|
||||
// The plugin can simultanious be used with two MPU6050 devices by adding multiple instances.
|
||||
// Originally released in the PlayGround as Plugin 118.
|
||||
|
||||
// Plugin var usage:
|
||||
// Globals - int16_t _P045_axis[3][5][2] Array to store sensorvalues of the axis
|
||||
// _P045_axis[0-2][x][x] = x, y, z axis
|
||||
// _P045_axis[x][0-4][x] = min values, max values, range (max-min), a-values, g-values.
|
||||
// _P045_axis[x][x][0-1] = device address: 0=0x68, 1=0x69
|
||||
// - long _P045_time[2] = Timer to check values each 5 seconds for each used device address.
|
||||
// Globals - int16_t _P118_axis[3][5][2] Array to store sensorvalues of the axis
|
||||
// _P118_axis[0-2][x][x] = x, y, z axis
|
||||
// _P118_axis[x][0-4][x] = min values, max values, range (max-min), a-values, g-values.
|
||||
// _P118_axis[x][x][0-1] = device address: 0=0x68, 1=0x69
|
||||
// - long _P118_time[2] = Timer to check values each 5 seconds for each used device address.
|
||||
|
||||
// Framework - Settings.TaskDevicePluginConfig[x][0] - Device address (0x68 | 0x69)
|
||||
// Settings.TaskDevicePluginConfig[x][1] - Instance function
|
||||
@@ -71,15 +70,15 @@
|
||||
#define MPU6050_PWR1_CLKSEL_BIT 2
|
||||
#define MPU6050_PWR1_CLKSEL_LENGTH 3
|
||||
|
||||
#define PLUGIN_045
|
||||
#define PLUGIN_ID_045 45
|
||||
#define PLUGIN_NAME_045 "MPU 6050 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_045 ""
|
||||
#define PLUGIN_118
|
||||
#define PLUGIN_ID_118 118
|
||||
#define PLUGIN_NAME_118 "MPU 6050 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_118 ""
|
||||
|
||||
int16_t _P045_axis[3][5][2]; // [xyz], [min/max/range,a,g], [0x68/0x69]
|
||||
long _P045_time[2];
|
||||
int16_t _P118_axis[3][5][2]; // [xyz], [min/max/range,a,g], [0x68/0x69]
|
||||
long _P118_time[2];
|
||||
|
||||
boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_118(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
@@ -88,7 +87,7 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_045;
|
||||
Device[++deviceCount].Number = PLUGIN_ID_118;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_I2C;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].ValueCount = 1; // Unfortunatly domoticz has no custom multivalue sensors.
|
||||
@@ -100,13 +99,13 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_045);
|
||||
string = F(PLUGIN_NAME_118);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_045));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_118));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -120,7 +119,7 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
int optionValues[2];
|
||||
optionValues[0] = 0x68;
|
||||
optionValues[1] = 0x69;
|
||||
string += F("<TR><TD>I2C Address:<TD><select name='plugin_045_address'>");
|
||||
string += F("<TR><TD>I2C Address:<TD><select name='plugin_118_address'>");
|
||||
for (byte x = 0; x < 2; x++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
@@ -135,7 +134,7 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
string += F("</select>");
|
||||
// Setup webform for instance function
|
||||
choice = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
string += F("<TR><TD>Function:<TD><select name='plugin_045_function'>");
|
||||
string += F("<TR><TD>Function:<TD><select name='plugin_118_function'>");
|
||||
options[0] = F("Movement detection");
|
||||
options[1] = F("Range acceleration X");
|
||||
options[2] = F("Range acceleration Y");
|
||||
@@ -164,13 +163,13 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
string += F("<TR><TD><TD>The thresholdvalues (0-65535) can be used to set a threshold for one or more<br>");
|
||||
string += F("axis. The axis will trigger when the range for that axis exceeds the threshold<br>");
|
||||
string += F("value. A value of 0 disables movement detection for that axis.");
|
||||
string += F("<TR><TD>Detection threshold X:<TD><input type='text' size='6' maxlength='6' name='plugin_045_threshold_x' value='");
|
||||
string += F("<TR><TD>Detection threshold X:<TD><input type='text' size='6' maxlength='6' name='plugin_118_threshold_x' value='");
|
||||
string += Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
string += F("'>");
|
||||
string += F("<TR><TD>Detection threshold Y:<TD><input type='text' size='6' maxlength='6' name='plugin_045_threshold_y' value='");
|
||||
string += F("<TR><TD>Detection threshold Y:<TD><input type='text' size='6' maxlength='6' name='plugin_118_threshold_y' value='");
|
||||
string += Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
string += F("'>");
|
||||
string += F("<TR><TD>Detection threshold Z:<TD><input type='text' size='6' maxlength='6' name='plugin_045_threshold_z' value='");
|
||||
string += F("<TR><TD>Detection threshold Z:<TD><input type='text' size='6' maxlength='6' name='plugin_118_threshold_z' value='");
|
||||
string += Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
string += F("'>");
|
||||
string += F("<TR><TD><TD>Each 30 seconds a counter for the detection window is increased plus all axis<br>");
|
||||
@@ -179,10 +178,10 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
string += F("the [min. detection count] and if found equal or larger, movement is detected.<br>");
|
||||
string += F("If in the next window the [min. detection count] value is not met, movement has stopped.");
|
||||
string += F("The [detection window] cannot be smaller than the [min. detection count].");
|
||||
string += F("<TR><TD>Min. detection count:<TD><input type='text' size='6' maxlength='6' name='plugin_045_threshold_counter' value='");
|
||||
string += F("<TR><TD>Min. detection count:<TD><input type='text' size='6' maxlength='6' name='plugin_118_threshold_counter' value='");
|
||||
string += Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
string += F("'>");
|
||||
string += F("<TR><TD>Detection window:<TD><input type='text' size='6' maxlength='6' name='plugin_045_threshold_window' value='");
|
||||
string += F("<TR><TD>Detection window:<TD><input type='text' size='6' maxlength='6' name='plugin_118_threshold_window' value='");
|
||||
string += Settings.TaskDevicePluginConfig[event->TaskIndex][6];
|
||||
string += F("'>");
|
||||
}
|
||||
@@ -193,19 +192,19 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
// Save the vars
|
||||
String plugin1 = WebServer.arg("plugin_045_address");
|
||||
String plugin1 = WebServer.arg("plugin_118_address");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_function");
|
||||
plugin1 = WebServer.arg("plugin_118_function");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_threshold_x");
|
||||
plugin1 = WebServer.arg("plugin_118_threshold_x");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_threshold_y");
|
||||
plugin1 = WebServer.arg("plugin_118_threshold_y");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_threshold_z");
|
||||
plugin1 = WebServer.arg("plugin_118_threshold_z");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][4] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_threshold_counter");
|
||||
plugin1 = WebServer.arg("plugin_118_threshold_counter");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][5] = plugin1.toInt();
|
||||
plugin1 = WebServer.arg("plugin_045_threshold_window");
|
||||
plugin1 = WebServer.arg("plugin_118_threshold_window");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][6] = plugin1.toInt();
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][6] < Settings.TaskDevicePluginConfig[event->TaskIndex][5]) {
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][6] = Settings.TaskDevicePluginConfig[event->TaskIndex][5];
|
||||
@@ -224,14 +223,14 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = devAddr;
|
||||
}
|
||||
// Initialize the MPU6050, for details look at the MPU6050 library: MPU6050::Initialize
|
||||
_P045_writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, MPU6050_CLOCK_PLL_XGYRO);
|
||||
_P045_writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, MPU6050_GYRO_FS_250);
|
||||
_P045_writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, MPU6050_ACCEL_FS_2);
|
||||
_P045_writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, 1, 0);
|
||||
_P118_writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, MPU6050_CLOCK_PLL_XGYRO);
|
||||
_P118_writeBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, MPU6050_GYRO_FS_250);
|
||||
_P118_writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, MPU6050_ACCEL_FS_2);
|
||||
_P118_writeBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, 1, 0);
|
||||
|
||||
// Read the MPU6050 once to clear out zeros (1st time reading MPU6050 returns all 0s)
|
||||
int16_t ax, ay, az, gx, gy, gz;
|
||||
_P045_getMotion6(devAddr, &ax, &ay, &az, &gx, &gy, &gz);
|
||||
_P118_getMotion6(devAddr, &ax, &ay, &az, &gx, &gy, &gz);
|
||||
|
||||
// Reset vars
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][7] = 0; // Last known value of "switch" is off
|
||||
@@ -248,38 +247,38 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
byte dev = devAddr & 1;
|
||||
|
||||
// Read the sensorvalues, we run this bit every 1/10th of a second
|
||||
_P045_getMotion6(devAddr, &_P045_axis[0][3][dev], &_P045_axis[1][3][dev], &_P045_axis[2][3][dev], &_P045_axis[0][4][dev], &_P045_axis[1][4][dev], &_P045_axis[2][4][dev]);
|
||||
_P118_getMotion6(devAddr, &_P118_axis[0][3][dev], &_P118_axis[1][3][dev], &_P118_axis[2][3][dev], &_P118_axis[0][4][dev], &_P118_axis[1][4][dev], &_P118_axis[2][4][dev]);
|
||||
// Set the minimum and maximum value for each axis a-value, overwrite previous values if smaller/larger
|
||||
_P045_trackMinMax(_P045_axis[0][3][dev], &_P045_axis[0][0][dev], &_P045_axis[0][1][dev]);
|
||||
_P045_trackMinMax(_P045_axis[1][3][dev], &_P045_axis[1][0][dev], &_P045_axis[1][1][dev]);
|
||||
_P045_trackMinMax(_P045_axis[2][3][dev], &_P045_axis[2][0][dev], &_P045_axis[2][1][dev]);
|
||||
_P118_trackMinMax(_P118_axis[0][3][dev], &_P118_axis[0][0][dev], &_P118_axis[0][1][dev]);
|
||||
_P118_trackMinMax(_P118_axis[1][3][dev], &_P118_axis[1][0][dev], &_P118_axis[1][1][dev]);
|
||||
_P118_trackMinMax(_P118_axis[2][3][dev], &_P118_axis[2][0][dev], &_P118_axis[2][1][dev]);
|
||||
// ^ current value @ 3 ^ min val @ 0 ^ max val @ 1
|
||||
|
||||
/* // Uncomment this block if you want to debug your MPU6050, but be prepared for a log overload
|
||||
String log = F("MPU6050 : axis values: ");
|
||||
log += _P045_axis[0][3][dev]
|
||||
log += _P118_axis[0][3][dev]
|
||||
log += F(", ");
|
||||
log += _P045_axis[1][3][dev];
|
||||
log += _P118_axis[1][3][dev];
|
||||
log += F(", ");
|
||||
log += _P045_axis[2][3][dev];
|
||||
log += _P118_axis[2][3][dev];
|
||||
log += F(", g values: ");
|
||||
log += _P045_axis[0][4][dev];
|
||||
log += _P118_axis[0][4][dev];
|
||||
log += F(", ");
|
||||
log += _P045_axis[1][4][dev];
|
||||
log += _P118_axis[1][4][dev];
|
||||
log += F(", ");
|
||||
log += _P045_axis[2][4][dev];
|
||||
log += _P118_axis[2][4][dev];
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
*/
|
||||
// Run this bit every 5 seconds per deviceaddress (not per instance)
|
||||
if ((_P045_time[dev] + 5000) < millis())
|
||||
if ((_P118_time[dev] + 5000) < millis())
|
||||
{
|
||||
_P045_time[dev] = millis();
|
||||
_P118_time[dev] = millis();
|
||||
|
||||
// Determine the maximum measured range of each axis
|
||||
for (uint8_t i=0; i<3; i++) {
|
||||
_P045_axis[i][2][dev] = abs(_P045_axis[i][1][dev] - _P045_axis[i][0][dev]);
|
||||
_P045_axis[i][0][dev] = _P045_axis[i][3][dev];
|
||||
_P045_axis[i][1][dev] = _P045_axis[i][3][dev];
|
||||
_P118_axis[i][2][dev] = abs(_P118_axis[i][1][dev] - _P118_axis[i][0][dev]);
|
||||
_P118_axis[i][0][dev] = _P118_axis[i][3][dev];
|
||||
_P118_axis[i][1][dev] = _P118_axis[i][3][dev];
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
@@ -290,8 +289,8 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
int devAddr = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
byte dev = devAddr & 1;
|
||||
int _P045_Function = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
switch (_P045_Function)
|
||||
int _P118_Function = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
switch (_P118_Function)
|
||||
{
|
||||
// Function 0 is for movement detection
|
||||
case 0:
|
||||
@@ -303,7 +302,7 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
// for each axis:
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][i + 2] != 0) { // not disabled, check threshold
|
||||
if (_P045_axis[i][2][dev] < Settings.TaskDevicePluginConfig[event->TaskIndex][i + 2]) { thresexceed = false; }
|
||||
if (_P118_axis[i][2][dev] < Settings.TaskDevicePluginConfig[event->TaskIndex][i + 2]) { thresexceed = false; }
|
||||
} else { count++; } // If disabled count + 1
|
||||
}
|
||||
if (count == 3) { thresexceed = false; } // If we counted to three, all three axis are disabled.
|
||||
@@ -326,10 +325,10 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
// Check if UserVar changed so we do not overload homecontroller with the same readings
|
||||
if (Settings.TaskDevicePluginConfigLong[event->TaskIndex][7] != UserVar[event->BaseVarIndex]) {
|
||||
success = true; // Update switch status
|
||||
Settings.TaskDevicePluginConfigLong[event->TaskIndex][7] = UserVar[event->BaseVarIndex];
|
||||
success = true;
|
||||
} else {
|
||||
success = false;
|
||||
success = false; // Do not update switch status
|
||||
}
|
||||
Settings.TaskDevicePluginConfigLong[event->TaskIndex][0] = 0; // reset threshold exceeded counter
|
||||
}
|
||||
@@ -341,9 +340,9 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
// All other functions are reading values. So extract xyz value and wanted type from function number:
|
||||
default: // [1-3]: range-values, [4-6]: a-values, [7-9]: g-values
|
||||
{
|
||||
uint8_t reqaxis = (_P045_Function - 1) % 3; // xyz -> eg: function 5(ay) (5-1) % 3 = 1 (y)
|
||||
uint8_t reqvar = ((_P045_Function - 1) / 3) + 2; // range, a, g -> eg: function 9(gz) ((9-1) / 3 = 2) + 2 = 4 (g)
|
||||
UserVar[event->BaseVarIndex] = float(_P045_axis[reqaxis][reqvar][dev]);
|
||||
uint8_t reqaxis = (_P118_Function - 1) % 3; // xyz -> eg: function 5(ay) (5-1) % 3 = 1 (y)
|
||||
uint8_t reqvar = ((_P118_Function - 1) / 3) + 2; // range, a, g -> eg: function 9(gz) ((9-1) / 3 = 2) + 2 = 4 (g)
|
||||
UserVar[event->BaseVarIndex] = float(_P118_axis[reqaxis][reqvar][dev]);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -354,7 +353,7 @@ boolean Plugin_045(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
void _P045_trackMinMax(int16_t current, int16_t *min, int16_t *max)
|
||||
void _P118_trackMinMax(int16_t current, int16_t *min, int16_t *max)
|
||||
// From nodemcu-laundry.ino by Nolan Gilley
|
||||
{
|
||||
if (current > *max)
|
||||
@@ -378,7 +377,7 @@ void _P045_trackMinMax(int16_t current, int16_t *min, int16_t *max)
|
||||
* @param gy 16-bit signed integer container for gyroscope Y-axis value
|
||||
* @param gz 16-bit signed integer container for gyroscope Z-axis value
|
||||
*/
|
||||
void _P045_getMotion6(uint8_t devAddr, int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) {
|
||||
void _P118_getMotion6(uint8_t devAddr, int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) {
|
||||
// From I2Cdev::readBytes and MPU6050::getMotion6, both by Jeff Rowberg
|
||||
uint8_t buffer[14];
|
||||
uint8_t count = 0;
|
||||
@@ -405,7 +404,7 @@ void _P045_getMotion6(uint8_t devAddr, int16_t* ax, int16_t* ay, int16_t* az, in
|
||||
* @param length Number of bits to write (not more than 8)
|
||||
* @param data Right-aligned value to write
|
||||
*/
|
||||
void _P045_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
|
||||
void _P118_writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) {
|
||||
// From I2Cdev::writeBits by Jeff Rowberg
|
||||
// 010 value to write
|
||||
// 76543210 bit numbers
|
||||
@@ -1,8 +1,8 @@
|
||||
//#######################################################################################################
|
||||
//######################## Plugin 039: Thermocouple (MAX6675 / MAX31855) ################################
|
||||
//#######################################################################################################
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
// Original work by Dominik
|
||||
//#######################################################################################################
|
||||
//######################## Plugin 120: Thermocouple (MAX6675 / MAX31855) ################################
|
||||
//#######################################################################################################
|
||||
|
||||
// Plugin Description
|
||||
// This Plugin reads the data from Thermocouples. You have to use an Adapter Board with a
|
||||
@@ -35,16 +35,17 @@
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#define PLUGIN_039
|
||||
#define PLUGIN_ID_039 39
|
||||
#define PLUGIN_NAME_039 "Temperature - Thermocouple"
|
||||
#define PLUGIN_VALUENAME1_039 "Temperature"
|
||||
#define PLUGIN_120
|
||||
#define PLUGIN_ID_120 120
|
||||
#define PLUGIN_NAME_120 "Temperature Thermocouple [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_120 "Temperature C"
|
||||
#define PLUGIN_VALUENAME2_120 "Temperature K"
|
||||
|
||||
uint8_t Plugin_039_SPI_CS_Pin = 15; // D8
|
||||
bool Plugin_039_SensorAttached = true;
|
||||
double Plugin_039_Celsius = 0.0;
|
||||
uint8_t Plugin_120_SPI_CS_Pin = 15; // D8
|
||||
bool Plugin_120_SensorAttached = true;
|
||||
double Plugin_120_Celsius = 0.0;
|
||||
|
||||
boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_120(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
@@ -52,14 +53,14 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_039;
|
||||
Device[++deviceCount].Number = PLUGIN_ID_120;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_DUAL; // 2 Messwerte
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].ValueCount = 2;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
@@ -68,13 +69,14 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_039);
|
||||
string = F(PLUGIN_NAME_120);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_039));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_120));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_120));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -85,16 +87,16 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
if (Settings.TaskDevicePin1[event->TaskIndex] != 0)
|
||||
{
|
||||
// Konvert the GPIO Pin to a Dogotal Puin Number first ...
|
||||
Plugin_039_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
Plugin_120_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
}
|
||||
|
||||
// set the slaveSelectPin as an output:
|
||||
pinMode(Plugin_039_SPI_CS_Pin, OUTPUT);
|
||||
pinMode(Plugin_120_SPI_CS_Pin, OUTPUT);
|
||||
// initialize SPI:
|
||||
SPI.setHwCs(false);
|
||||
SPI.begin();
|
||||
|
||||
addLog(LOG_LEVEL_INFO, (char*)"P039 : SPI Init");
|
||||
addLog(LOG_LEVEL_INFO, (char*)"P120 : SPI Init");
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -113,7 +115,7 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
optionValues[0] = 1;
|
||||
optionValues[1] = 2;
|
||||
//optionValues[2] = 3;
|
||||
string += F("<TR><TD>Adapter IC:<TD><select name='plugin_039_maxtype'>");
|
||||
string += F("<TR><TD>Adapter IC:<TD><select name='plugin_120_maxtype'>");
|
||||
for (byte x = 0; x < 2; x++)
|
||||
{
|
||||
string += F("<option value='");
|
||||
@@ -133,7 +135,7 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_039_maxtype");
|
||||
String plugin1 = WebServer.arg("plugin_120_maxtype");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
success = true;
|
||||
break;
|
||||
@@ -147,25 +149,28 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
// Get CS Pin
|
||||
// Konvert the GPIO Pin to a Dogotal Puin Number first ...
|
||||
Plugin_039_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
Plugin_120_SPI_CS_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
|
||||
switch (MaxType) {
|
||||
case 1: // MAX6675
|
||||
Plugin_039_Celsius = readMax6675();
|
||||
Plugin_120_Celsius = readMax6675();
|
||||
break;
|
||||
case 2: // MAX31855
|
||||
Plugin_039_Celsius = readMax31855();
|
||||
Plugin_120_Celsius = readMax31855();
|
||||
break;
|
||||
case 3: // MAX31865 (not implemented yet)
|
||||
//do something when var equals 2
|
||||
break;
|
||||
}
|
||||
|
||||
if (Plugin_039_Celsius != NAN)
|
||||
if (Plugin_120_Celsius != NAN)
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = Plugin_039_Celsius;
|
||||
String log = F("P039 : Temperature ");
|
||||
UserVar[event->BaseVarIndex] = Plugin_120_Celsius;
|
||||
UserVar[event->BaseVarIndex + 1] = CelsiusToFahrenheit(Plugin_120_Celsius);
|
||||
String log = F("P120 : C : ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
log += F(" - F : ");
|
||||
log += UserVar[event->BaseVarIndex + 1];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
}
|
||||
@@ -173,7 +178,7 @@ boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
UserVar[event->BaseVarIndex + 1] = NAN;
|
||||
String log = F("P039 : No Sensor attached !");
|
||||
String log = F("P120 : No Sensor attached !");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = false;
|
||||
}
|
||||
@@ -188,16 +193,16 @@ double readMax6675()
|
||||
{
|
||||
uint16_t rawvalue = 0;
|
||||
// take the SS pin low to select the chip:
|
||||
digitalWrite(Plugin_039_SPI_CS_Pin, LOW);
|
||||
// String log = F("P039 : CS Pin : ");
|
||||
// log += Plugin_039_SPI_CS_Pin;
|
||||
digitalWrite(Plugin_120_SPI_CS_Pin, LOW);
|
||||
// String log = F("P120 : CS Pin : ");
|
||||
// log += Plugin_120_SPI_CS_Pin;
|
||||
// addLog(LOG_LEVEL_INFO, log);
|
||||
// "transfer" 0x0 and read the Data from the Chip
|
||||
rawvalue = SPI.transfer16(0x0);
|
||||
// take the SS pin high to de-select the chip:
|
||||
digitalWrite(Plugin_039_SPI_CS_Pin, HIGH);
|
||||
digitalWrite(Plugin_120_SPI_CS_Pin, HIGH);
|
||||
|
||||
String log = F("P039 : MAX6675 : RAW - BIN:");
|
||||
String log = F("P120 : MAX6675 : RAW - BIN:");
|
||||
log += String(rawvalue, BIN);
|
||||
log += " HEX:";
|
||||
log += String(rawvalue, HEX);
|
||||
@@ -209,9 +214,9 @@ double readMax6675()
|
||||
// Bit D2 is normally low and goes high if the thermocouple input is open. In order to allow the operation of the
|
||||
// open thermocouple detector, T- must be grounded. Make the ground connection as close to the GND pin
|
||||
// as possible.
|
||||
Plugin_039_SensorAttached = !(rawvalue & 0x0004);
|
||||
Plugin_120_SensorAttached = !(rawvalue & 0x0004);
|
||||
|
||||
if (Plugin_039_SensorAttached)
|
||||
if (Plugin_120_SensorAttached)
|
||||
{
|
||||
// Shift RAW value 3 Bits to the right to get the data
|
||||
rawvalue >>= 3;
|
||||
@@ -229,7 +234,7 @@ double readMax31855()
|
||||
{
|
||||
uint32_t rawvalue = 0;
|
||||
// take the SS pin low to select the chip:
|
||||
digitalWrite(Plugin_039_SPI_CS_Pin, LOW);
|
||||
digitalWrite(Plugin_120_SPI_CS_Pin, LOW);
|
||||
// "transfer" 0x0 and read the MSB Data from the Chip
|
||||
rawvalue = SPI.transfer16(0x0);
|
||||
// Shift MSB 16 Bits to the left
|
||||
@@ -237,9 +242,9 @@ double readMax31855()
|
||||
// "transfer" 0x0 and read the LSB Data from the Chip
|
||||
rawvalue |= SPI.transfer16(0x0);
|
||||
// take the SS pin high to de-select the chip:
|
||||
digitalWrite(Plugin_039_SPI_CS_Pin, HIGH);
|
||||
digitalWrite(Plugin_120_SPI_CS_Pin, HIGH);
|
||||
|
||||
String log = F("P039 : MAX31855 : RAW - BIN:");
|
||||
String log = F("P120 : MAX31855 : RAW - BIN:");
|
||||
log += String(rawvalue, BIN);
|
||||
log += " HEX:";
|
||||
log += String(rawvalue, HEX);
|
||||
@@ -248,16 +253,16 @@ double readMax31855()
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// D16 - This bit reads at 1 when any of the SCV, SCG, or OC faults are active. Default value is 0.
|
||||
Plugin_039_SensorAttached = !(rawvalue & 0x00010000);
|
||||
Plugin_120_SensorAttached = !(rawvalue & 0x00010000);
|
||||
|
||||
if (Plugin_039_SensorAttached)
|
||||
if (Plugin_120_SensorAttached)
|
||||
{
|
||||
// Data is D[31:18]
|
||||
// Shift RAW value 18 Bits to the right to get the data
|
||||
rawvalue >>= 18;
|
||||
|
||||
// Check for negative Values
|
||||
// +25.00 0000 0001 1001 00
|
||||
// +25.00 0000 0001 1001 00
|
||||
// 0.00 0000 0000 0000 00
|
||||
// -0.25 1111 1111 1111 11
|
||||
// -1.00 1111 1111 1111 00
|
||||
@@ -265,11 +270,11 @@ double readMax31855()
|
||||
if (rawvalue & 0x2000) // Bit 31=1 -> neg Values
|
||||
{
|
||||
// Negate all Bits
|
||||
rawvalue = ~rawvalue;
|
||||
// Add 1 and make negative
|
||||
rawvalue = ~rawvalue;
|
||||
// Add 1 and make negative
|
||||
rawvalue = (rawvalue + 1) * -1;
|
||||
}
|
||||
|
||||
|
||||
// Calculate Celsius
|
||||
return rawvalue * 0.25;
|
||||
}
|
||||
@@ -278,3 +283,10 @@ double readMax31855()
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Celsius to Fahrenheit
|
||||
double CelsiusToFahrenheit(double celsius) {
|
||||
return celsius * 9.0 / 5.0 + 32;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
/*
|
||||
|
||||
This plug in is written by Dmitry (rel22 ___ inbox.ru)
|
||||
@@ -8,33 +9,31 @@
|
||||
DevicePin2 - is TX for ESP
|
||||
*/
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_049
|
||||
#define PLUGIN_ID_049 49
|
||||
#define PLUGIN_NAME_049 "NDIR CO2 Sensor MH-Z19 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_049 "PPM"
|
||||
#define PLUGIN_READ_TIMEOUT 3000
|
||||
#define PLUGIN_149
|
||||
#define PLUGIN_ID_149 149
|
||||
#define PLUGIN_NAME_149 "NDIR CO2 Sensor MH-Z19 [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_149 "PPM"
|
||||
|
||||
boolean Plugin_049_init = false;
|
||||
boolean Plugin_149_init = false;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial *Plugin_049_S8;
|
||||
SoftwareSerial *Plugin_149_S8;
|
||||
|
||||
// 9-bytes CMD PPM read command
|
||||
byte mhzCmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
|
||||
byte mhzResp[9]; // 9 bytes bytes response
|
||||
|
||||
boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_149(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
bool success = false;
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_049;
|
||||
Device[++deviceCount].Number = PLUGIN_ID_149;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
@@ -50,28 +49,20 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_049);
|
||||
string = F(PLUGIN_NAME_149);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_049));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_149));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_049_S8 = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
Plugin_049_S8->begin(9600);
|
||||
String log = F("MHZ19: Init OK ");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
//delay first read, because hardware needs to initialize on cold boot
|
||||
//otherwise we get a weird value or read error
|
||||
timerSensor[event->TaskIndex] = millis() + 15000;
|
||||
|
||||
Plugin_049_init = true;
|
||||
Plugin_149_init = true;
|
||||
Plugin_149_S8 = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -79,51 +70,27 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
|
||||
if (Plugin_049_init)
|
||||
if (Plugin_149_init)
|
||||
{
|
||||
//send read PPM command
|
||||
int nbBytesSent = Plugin_049_S8->write(mhzCmd, 9);
|
||||
if (nbBytesSent != 9) {
|
||||
String log = F("MHZ19: Error, nb bytes sent != 9 : ");
|
||||
log += nbBytesSent;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
// get response
|
||||
memset(mhzResp, 0, sizeof(mhzResp));
|
||||
|
||||
long start = millis();
|
||||
int counter = 0;
|
||||
while (((millis() - start) < PLUGIN_READ_TIMEOUT) && (counter < 9)) {
|
||||
if (Plugin_049_S8->available() > 0) {
|
||||
mhzResp[counter++] = Plugin_049_S8->read();
|
||||
} else {
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
if (counter < 9){
|
||||
String log = F("MHZ19: Error, timeout while trying to read");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
unsigned int ppm = 0;
|
||||
Plugin_149_S8->write(mhzCmd, 9);
|
||||
memset(mhzResp, 0, 9);
|
||||
Plugin_149_S8->readBytes(mhzResp, 9);
|
||||
int i;
|
||||
unsigned int ppm = 0;
|
||||
byte crc = 0;
|
||||
for (i = 1; i < 8; i++) crc+=mhzResp[i];
|
||||
crc = 255 - crc;
|
||||
crc++;
|
||||
|
||||
if ( !(mhzResp[0] == 0xFF && mhzResp[1] == 0x86 && mhzResp[8] == crc) ) {
|
||||
String log = F("MHZ19: Read error : CRC = ");
|
||||
String log = F("MHZ19: CRC error: ");
|
||||
log += String(crc); log += " / "; log += String(mhzResp[8]);
|
||||
log += " bytes read => ";for (i = 0; i < 9; i++) {log += mhzResp[i];log += "/" ;}
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
|
||||
success = false;
|
||||
break;
|
||||
|
||||
} else {
|
||||
//calculate CO2 PPM
|
||||
|
||||
unsigned int mhzRespHigh = (unsigned int) mhzResp[2];
|
||||
unsigned int mhzRespLow = (unsigned int) mhzResp[3];
|
||||
ppm = (256*mhzRespHigh) + mhzRespLow;
|
||||
@@ -141,5 +108,4 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 046: Ventus W266 [Testing] ################################
|
||||
//#################################### Plugin 186: Ventus W266 [Testing] ################################
|
||||
//#######################################################################################################
|
||||
|
||||
// Purpose: Sniff the data received by the Ventus W266 display unit and send it to Domoticz
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
// The plugin uses two buffers, ine for the ISR routines and one for the other plugin instances.
|
||||
|
||||
// This plugin was originally released into th eplayground as Plugin 186, it is assimilated into the core as 046.
|
||||
// Why plugin nr 186? Well 266 is not possible, 206 (id on the back of the unit) is nit within the
|
||||
// playground range and the W186 is an additinal external thermometer for the Ventus W266.
|
||||
// The Ventus W266 is also known as the Renkforce W205GU.
|
||||
@@ -59,6 +58,7 @@
|
||||
// ld=lightningstorm-distance (km, 3F is max) > The distance to the stormfront in km
|
||||
// lllh=strikecount-low/high (#) > A 16 bit integer holding the number of detected lightning strikes, low byte first
|
||||
// crc > poly 0x31, init 0xff, revin&revout, xorout 0x00. Like Maxim 1-wire but with a 0xff initvalue. Crc is calculated over bytes 1-22
|
||||
//
|
||||
|
||||
// Events:
|
||||
// None
|
||||
@@ -67,56 +67,57 @@
|
||||
// None
|
||||
|
||||
// Current state / limitations:
|
||||
// 1.0 Initial release. All values are always visible although sometimes only one is really used with domoticz.
|
||||
// 1.0 Initial release. All values are always visible although sometimes
|
||||
// only one is really used with domoticz.
|
||||
// Needs work on a sliding window for the lightning detection.
|
||||
// When porting be beware of the fact that the esp8266 uses 4 bytes as an int when reading the temperature.
|
||||
//
|
||||
// Exploits the fact that event->sensorType is not reset after PLUGIN_READ.
|
||||
|
||||
// This plugin is based on the work of the Plugin 199: RF KaKu receiver/sender and Plugin 026: Analog.
|
||||
// CRC calculation is based on the works by Paul Stoffregen from the 1-Wire arduino library. Special
|
||||
// thanks to Greg Cook and the team behind reveng.sourceforge.net.
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_046_DEBUG true // Shows recieved frames and crc in log@INFO
|
||||
#define PLUGIN_186_DEBUG true // Shows recieved frames and crc in log@INFO
|
||||
|
||||
#define PLUGIN_046 // Mandatory framework constants
|
||||
#define PLUGIN_ID_046 46
|
||||
#define PLUGIN_NAME_046 "Ventus W266 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_046 ""
|
||||
#define PLUGIN_VALUENAME2_046 ""
|
||||
#define PLUGIN_VALUENAME3_046 ""
|
||||
#define PLUGIN_186 // Mandatory framework constants
|
||||
#define PLUGIN_ID_186 186
|
||||
#define PLUGIN_NAME_186 "Ventus W266 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_186 ""
|
||||
#define PLUGIN_VALUENAME2_186 ""
|
||||
#define PLUGIN_VALUENAME3_186 ""
|
||||
|
||||
#define Plugin_046_MagicByte 0x7F // When we read this byte on MOSI, switch to MISO
|
||||
#define Plugin_046_RAW_BUFFER_SIZE 24 // Payload is 23 bytes, added space for header
|
||||
#define Plugin_046_Payload 23
|
||||
#define Plugin_186_MagicByte 0x7F // When we read this byte on MOSI, switch to MISO
|
||||
#define Plugin_186_RAW_BUFFER_SIZE 24 // Payload is 23 bytes, added space for header
|
||||
#define Plugin_186_Payload 23
|
||||
|
||||
int8_t Plugin_046_MOSIpin = -1; // GPIO pins
|
||||
int8_t Plugin_046_SCLKpin = -1;
|
||||
int8_t Plugin_046_nSELpin = -1;
|
||||
int8_t Plugin_046_MISOpin = -1;
|
||||
int8_t Plugin_186_MOSIpin = -1; // GPIO pins
|
||||
int8_t Plugin_186_SCLKpin = -1;
|
||||
int8_t Plugin_186_nSELpin = -1;
|
||||
int8_t Plugin_186_MISOpin = -1;
|
||||
// Vars used in data collection:
|
||||
byte Plugin_046_ISR_Buffer[Plugin_046_RAW_BUFFER_SIZE]; // Buffer used in ISR routine
|
||||
//Test data: volatile byte Plugin_046_databuffer[] = {0x7F, 0x98, 0x33, 0x1A, 0xB0, 0x00, 0x00, 0xB0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3F, 0x8A, 0x25, 0x00, 0x49, 0x00}; // Buffer used by other instances
|
||||
byte Plugin_046_databuffer[Plugin_046_RAW_BUFFER_SIZE]; // Buffer used by other instances
|
||||
boolean Plugin_046_RecieveActive = false; // Active session in progress
|
||||
boolean Plugin_046_MasterSlave = false; // Which pin o read? false=MOSI, true=MISO
|
||||
boolean Plugin_046_newData = false; // "Valid" data ready, please process
|
||||
byte Plugin_046_bitpointer; // Pointer for recieved bit
|
||||
byte Plugin_046_bytepointer; // Pointe for ISR recieve buffer
|
||||
byte Plugin_046_recievedData; // Byte to store recieved bits
|
||||
byte Plugin_186_ISR_Buffer[Plugin_186_RAW_BUFFER_SIZE]; // Buffer used in ISR routine
|
||||
//Test data: volatile byte Plugin_186_databuffer[] = {0x7F, 0x98, 0x33, 0x1A, 0xB0, 0x00, 0x00, 0xB0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3F, 0x8A, 0x25, 0x00, 0x49, 0x00}; // Buffer used by other instances
|
||||
byte Plugin_186_databuffer[Plugin_186_RAW_BUFFER_SIZE]; // Buffer used by other instances
|
||||
boolean Plugin_186_RecieveActive = false; // Active session in progress
|
||||
boolean Plugin_186_MasterSlave = false; // Which pin o read? false=MOSI, true=MISO
|
||||
boolean Plugin_186_newData = false; // "Valid" data ready, please process
|
||||
byte Plugin_186_bitpointer; // Pointer for recieved bit
|
||||
byte Plugin_186_bytepointer; // Pointe for ISR recieve buffer
|
||||
byte Plugin_186_recievedData; // Byte to store recieved bits
|
||||
|
||||
// Vars used for interpreting the data:
|
||||
volatile unsigned long Plugin_046_lastrainctr; // Keep track of wdcounter (1/2 min tick)
|
||||
volatile int Plugin_046_lastraincount; // Last rain count
|
||||
volatile float Plugin_046_rainmmph = 0;
|
||||
volatile unsigned long Plugin_046_laststrikectr; // Keep track of wdcounter (1/2 min tick)
|
||||
volatile unsigned int Plugin_046_laststrikecount; // Last number of strikes
|
||||
volatile int Plugin_046_strikesph = 0;
|
||||
volatile unsigned long Plugin_186_lastrainctr; // Keep track of wdcounter (1/2 min tick)
|
||||
volatile int Plugin_186_lastraincount; // Last rain count
|
||||
volatile float Plugin_186_rainmmph = 0;
|
||||
volatile unsigned long Plugin_186_laststrikectr; // Keep track of wdcounter (1/2 min tick)
|
||||
volatile unsigned int Plugin_186_laststrikecount; // Last number of strikes
|
||||
volatile int Plugin_186_strikesph = 0;
|
||||
|
||||
void Plugin_046_ISR_nSEL() ICACHE_RAM_ATTR; // Interrupt routines
|
||||
void Plugin_046_ISR_SCLK() ICACHE_RAM_ATTR;
|
||||
void Plugin_186_ISR_nSEL() ICACHE_RAM_ATTR; // Interrupt routines
|
||||
void Plugin_186_ISR_SCLK() ICACHE_RAM_ATTR;
|
||||
|
||||
boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_186(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
@@ -124,7 +125,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_046;
|
||||
Device[++deviceCount].Number = PLUGIN_ID_186;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUMMY; // Nothing else really fit the bill ...
|
||||
Device[deviceCount].VType = SENSOR_TYPE_DUAL; // New type, see ESPEasy.ino
|
||||
Device[deviceCount].Ports = 0;
|
||||
@@ -156,7 +157,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
for (byte x = 0; x < nrchoices; x++) {
|
||||
optionValues[x] = x;
|
||||
}
|
||||
string += F("<TR><TD>Plugin function:<TD><select name='plugin_046'>");
|
||||
string += F("<TR><TD>Plugin function:<TD><select name='plugin_186'>");
|
||||
for (byte x = 0; x < nrchoices; x++) {
|
||||
string += F("<option value='");
|
||||
string += optionValues[x];
|
||||
@@ -244,7 +245,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String plugin1 = WebServer.arg("plugin_046");
|
||||
String plugin1 = WebServer.arg("plugin_186");
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = plugin1.toInt();
|
||||
if (plugin1.toInt()==0) {
|
||||
String plugin2 = WebServer.arg("taskdevicepin1");
|
||||
@@ -262,15 +263,15 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_046);
|
||||
string = F(PLUGIN_NAME_186);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_046));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_046));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_046));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_186));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_186));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_186));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -281,23 +282,23 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
case (0):
|
||||
{
|
||||
Plugin_046_MOSIpin = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
Plugin_046_SCLKpin = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
Plugin_046_nSELpin = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
Plugin_046_MISOpin = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int8_t total = Plugin_046_MOSIpin + Plugin_046_SCLKpin + Plugin_046_nSELpin + Plugin_046_MISOpin;
|
||||
Plugin_186_MOSIpin = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
Plugin_186_SCLKpin = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
Plugin_186_nSELpin = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
Plugin_186_MISOpin = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
int8_t total = Plugin_186_MOSIpin + Plugin_186_SCLKpin + Plugin_186_nSELpin + Plugin_186_MISOpin;
|
||||
if (total > 6) { // All pins configured?
|
||||
pinMode(Plugin_046_MOSIpin, INPUT);
|
||||
pinMode(Plugin_046_SCLKpin, INPUT);
|
||||
pinMode(Plugin_046_nSELpin, INPUT);
|
||||
pinMode(Plugin_046_MISOpin, INPUT);
|
||||
Plugin_046_databuffer[0] = 0; // buffer is "empty"
|
||||
Plugin_046_lastrainctr = 0;
|
||||
Plugin_046_lastraincount = -1;
|
||||
Plugin_046_laststrikectr = 0;
|
||||
Plugin_046_laststrikecount = -1;
|
||||
attachInterrupt(Plugin_046_SCLKpin, Plugin_046_ISR_SCLK, RISING);
|
||||
attachInterrupt(Plugin_046_nSELpin, Plugin_046_ISR_nSEL, CHANGE);
|
||||
pinMode(Plugin_186_MOSIpin, INPUT);
|
||||
pinMode(Plugin_186_SCLKpin, INPUT);
|
||||
pinMode(Plugin_186_nSELpin, INPUT);
|
||||
pinMode(Plugin_186_MISOpin, INPUT);
|
||||
Plugin_186_databuffer[0] = 0; // buffer is "empty"
|
||||
Plugin_186_lastrainctr = 0;
|
||||
Plugin_186_lastraincount = -1;
|
||||
Plugin_186_laststrikectr = 0;
|
||||
Plugin_186_laststrikecount = -1;
|
||||
attachInterrupt(Plugin_186_SCLKpin, Plugin_186_ISR_SCLK, RISING);
|
||||
attachInterrupt(Plugin_186_nSELpin, Plugin_186_ISR_nSEL, CHANGE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -308,14 +309,14 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] == 0) {
|
||||
if (Plugin_046_newData) {
|
||||
if (Plugin_186_newData) {
|
||||
uint8_t crc = 0xff; // init = 0xff
|
||||
char data; // CRC = MAXIM with modified init: poly 0x31, init 0xff, refin 1; refout 1, xorout 0x00
|
||||
// Copy recieved data to buffer and check CRC
|
||||
Plugin_046_databuffer[0] = Plugin_046_ISR_Buffer[0];
|
||||
for (int i = 1; i < Plugin_046_bytepointer; i++) {
|
||||
data = Plugin_046_ISR_Buffer[i];
|
||||
Plugin_046_databuffer[i] = data;
|
||||
Plugin_186_databuffer[0] = Plugin_186_ISR_Buffer[0];
|
||||
for (int i = 1; i < Plugin_186_bytepointer; i++) {
|
||||
data = Plugin_186_ISR_Buffer[i];
|
||||
Plugin_186_databuffer[i] = data;
|
||||
for (int j = 0; j < 8; j++) // crc routine from Jim Studt
|
||||
{ // Onewire library
|
||||
uint8_t mix = (crc ^ data) & 0x01;
|
||||
@@ -324,9 +325,9 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
data >>= 1;
|
||||
}
|
||||
}
|
||||
Plugin_046_MasterSlave = false;
|
||||
Plugin_046_newData = false;
|
||||
if (PLUGIN_046_DEBUG) {
|
||||
Plugin_186_MasterSlave = false;
|
||||
Plugin_186_newData = false;
|
||||
if (PLUGIN_186_DEBUG) {
|
||||
String log = "Ventus W266 Rcvd(";
|
||||
log += hour();
|
||||
log += ":";
|
||||
@@ -336,14 +337,14 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
if (tm.Second < 10) { log += "0"; }
|
||||
log += tm.Second;
|
||||
log += ") ";
|
||||
for (int i = 0; i < Plugin_046_Payload; i++) {
|
||||
for (int i = 0; i < Plugin_186_Payload; i++) {
|
||||
if ((i==2)||(i==3)||(i==4)||(i==9)||(i==10)||(i==14)||(i==17)||(i==18)||(i==20)) {
|
||||
log += ":";
|
||||
}
|
||||
char myHex = (Plugin_046_databuffer[i] >> 4) + 0x30;
|
||||
char myHex = (Plugin_186_databuffer[i] >> 4) + 0x30;
|
||||
if (myHex > 0x39) { myHex += 7; }
|
||||
log += myHex;
|
||||
myHex = (Plugin_046_databuffer[i] & 0x0f) + 0x30;
|
||||
myHex = (Plugin_186_databuffer[i] & 0x0f) + 0x30;
|
||||
if (myHex > 0x39) { myHex += 7; }
|
||||
log += myHex;
|
||||
}
|
||||
@@ -358,7 +359,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
if (crc != 00)
|
||||
{
|
||||
Plugin_046_databuffer[0] = 0; // Not MagicByte, so not valid.
|
||||
Plugin_186_databuffer[0] = 0; // Not MagicByte, so not valid.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -368,7 +369,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
if (Plugin_046_databuffer[0] == Plugin_046_MagicByte) // buffer[0] should be the MagicByte if valid
|
||||
if (Plugin_186_databuffer[0] == Plugin_186_MagicByte) // buffer[0] should be the MagicByte if valid
|
||||
{
|
||||
UserVar[event->BaseVarIndex + 1] = 0;
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0]; // Which instance?
|
||||
@@ -376,10 +377,10 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
case (0):
|
||||
{
|
||||
int myTemp = int((Plugin_046_databuffer[5] * 256) + Plugin_046_databuffer[4]);
|
||||
int myTemp = int((Plugin_186_databuffer[5] * 256) + Plugin_186_databuffer[4]);
|
||||
if (myTemp > 0x8000) { myTemp |= 0xffff0000; } // int @ esp8266 = 32 bits!
|
||||
float temperature = float(myTemp) / 10.0; // Temperature
|
||||
byte myHum = (Plugin_046_databuffer[2] >> 4) * 10 + (Plugin_046_databuffer[2] & 0x0f);
|
||||
byte myHum = (Plugin_186_databuffer[2] >> 4) * 10 + (Plugin_186_databuffer[2] & 0x0f);
|
||||
float humidity = float(myHum);
|
||||
UserVar[event->BaseVarIndex] = temperature;
|
||||
UserVar[event->BaseVarIndex + 1] = humidity;
|
||||
@@ -388,10 +389,10 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
case (1):
|
||||
{
|
||||
float average = float((Plugin_046_databuffer[11] << 8) + Plugin_046_databuffer[10]) / 10; // Wind speed average in m/s
|
||||
float gust = float((Plugin_046_databuffer[13] << 8) + Plugin_046_databuffer[12]) / 10; // Wind speed gust in m/s
|
||||
float bearing = float(Plugin_046_databuffer[9] & 0x0f) * 22.5; // Wind bearing (0-359)
|
||||
UserVar[event->BaseVarIndex] = bearing; // degrees
|
||||
float average = float((Plugin_186_databuffer[11]) * 256 + Plugin_186_databuffer[10]); // Wind speed average in 10 * m/s
|
||||
float gust = float((Plugin_186_databuffer[13]) * 256 + Plugin_186_databuffer[12]); // Wind speed gust in 10 * m/s
|
||||
float bearing = float(Plugin_186_databuffer[9] & 0x0f) * 22.5; // Wind bearing (0-359)
|
||||
UserVar[event->BaseVarIndex] = bearing; // degrees
|
||||
UserVar[event->BaseVarIndex + 1] = average;
|
||||
UserVar[event->BaseVarIndex + 2] = gust;
|
||||
event->sensorType = SENSOR_TYPE_WIND;
|
||||
@@ -399,78 +400,78 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
case (2):
|
||||
{
|
||||
float raincnt = float(((Plugin_046_databuffer[15]) * 256 + Plugin_046_databuffer[14]) / 4);
|
||||
float raincnt = float(((Plugin_186_databuffer[15]) * 256 + Plugin_186_databuffer[14]) / 4);
|
||||
int rainnow = int(raincnt);
|
||||
if (wdcounter < Plugin_046_lastrainctr) { Plugin_046_lastrainctr = wdcounter; }
|
||||
if (Plugin_046_lastrainctr > (wdcounter + 10)) // 5 min interval
|
||||
if (wdcounter < Plugin_186_lastrainctr) { Plugin_186_lastrainctr = wdcounter; }
|
||||
if (Plugin_186_lastrainctr > (wdcounter + 10)) // 5 min interval
|
||||
{
|
||||
Plugin_046_lastrainctr = wdcounter;
|
||||
if (rainnow > Plugin_046_lastraincount)
|
||||
Plugin_186_lastrainctr = wdcounter;
|
||||
if (rainnow > Plugin_186_lastraincount)
|
||||
{ // per 5 min * 12 = per hour
|
||||
Plugin_046_rainmmph = float(rainnow - Plugin_046_lastraincount) * 12;
|
||||
Plugin_046_lastraincount = rainnow;
|
||||
Plugin_186_rainmmph = float(rainnow - Plugin_186_lastraincount) * 12;
|
||||
Plugin_186_lastraincount = rainnow;
|
||||
} else {
|
||||
Plugin_046_rainmmph = 0;
|
||||
Plugin_186_rainmmph = 0;
|
||||
}
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = Plugin_046_rainmmph;
|
||||
UserVar[event->BaseVarIndex] = Plugin_186_rainmmph;
|
||||
UserVar[event->BaseVarIndex + 1] = raincnt;
|
||||
break;
|
||||
}
|
||||
case (3):
|
||||
{
|
||||
float uvindex = float((Plugin_046_databuffer[17]) / 10);
|
||||
float uvindex = float((Plugin_186_databuffer[17]) / 10);
|
||||
UserVar[event->BaseVarIndex] = uvindex;
|
||||
break;
|
||||
}
|
||||
case (4):
|
||||
{
|
||||
int strikes = 0;
|
||||
int strikesnow = int((Plugin_046_databuffer[21]) * 256 + Plugin_046_databuffer[20]);
|
||||
if (wdcounter < Plugin_046_laststrikectr) { Plugin_046_laststrikectr = wdcounter; }
|
||||
if (Plugin_046_laststrikectr > (wdcounter + 10)) // 5 min interval
|
||||
int strikesnow = int((Plugin_186_databuffer[21]) * 256 + Plugin_186_databuffer[20]);
|
||||
if (wdcounter < Plugin_186_laststrikectr) { Plugin_186_laststrikectr = wdcounter; }
|
||||
if (Plugin_186_laststrikectr > (wdcounter + 10)) // 5 min interval
|
||||
{
|
||||
Plugin_046_laststrikectr = wdcounter;
|
||||
if (strikesnow > Plugin_046_laststrikecount)
|
||||
Plugin_186_laststrikectr = wdcounter;
|
||||
if (strikesnow > Plugin_186_laststrikecount)
|
||||
{
|
||||
Plugin_046_strikesph = strikesnow - Plugin_046_laststrikecount;
|
||||
Plugin_046_laststrikecount = strikesnow;
|
||||
Plugin_186_strikesph = strikesnow - Plugin_186_laststrikecount;
|
||||
Plugin_186_laststrikecount = strikesnow;
|
||||
} else {
|
||||
Plugin_046_strikesph = 0;
|
||||
Plugin_186_strikesph = 0;
|
||||
}
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_046_strikesph);
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_186_strikesph);
|
||||
break;
|
||||
}
|
||||
case (5):
|
||||
{
|
||||
float distance = float(-1);
|
||||
if (Plugin_046_databuffer[18] != 0x3F )
|
||||
if (Plugin_186_databuffer[18] != 0x3F )
|
||||
{
|
||||
distance = float(Plugin_046_databuffer[18]);
|
||||
distance = float(Plugin_186_databuffer[18]);
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = distance;
|
||||
break;
|
||||
}
|
||||
case (6):
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_046_databuffer[6]);
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_186_databuffer[6]);
|
||||
break;
|
||||
}
|
||||
case (7):
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_046_databuffer[16]);
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_186_databuffer[16]);
|
||||
break;
|
||||
}
|
||||
case (8):
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_046_databuffer[19]);
|
||||
UserVar[event->BaseVarIndex] = float(Plugin_186_databuffer[19]);
|
||||
break;
|
||||
}
|
||||
} // switch
|
||||
success = true;
|
||||
} else {
|
||||
success = false; // No data received yet or incorrect CRC so do not publish any data
|
||||
success = false;
|
||||
}
|
||||
break;
|
||||
} // case READ
|
||||
@@ -478,47 +479,47 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
void Plugin_046_ISR_nSEL() // Interrupt on nSEL change
|
||||
void Plugin_186_ISR_nSEL() // Interrupt on nSEL change
|
||||
{
|
||||
if (digitalRead(Plugin_046_nSELpin)) {
|
||||
Plugin_046_RecieveActive = false; // nSEL high? Recieve done.
|
||||
if (Plugin_046_MasterSlave) { // If MISO not active, no data recieved
|
||||
if (Plugin_046_bytepointer == Plugin_046_Payload) { // If not 23 then bad datapacket
|
||||
Plugin_046_newData = true; // We have new data!
|
||||
if (digitalRead(Plugin_186_nSELpin)) {
|
||||
Plugin_186_RecieveActive = false; // nSEL high? Recieve done.
|
||||
if (Plugin_186_MasterSlave) { // If MISO not active, no data recieved
|
||||
if (Plugin_186_bytepointer == Plugin_186_Payload) { // If not 23 then bad datapacket
|
||||
Plugin_186_newData = true; // We have new data!
|
||||
}
|
||||
}
|
||||
} else { // nSEL low? Start recieve
|
||||
if (!Plugin_046_newData) { // Only accept new data if the old is processed
|
||||
Plugin_046_bitpointer = 7; // reset pointer (MSB first)
|
||||
Plugin_046_bytepointer = 0; // reset pointers & flags
|
||||
Plugin_046_MasterSlave = false;
|
||||
Plugin_046_RecieveActive = true; // We are now recieving data
|
||||
if (!Plugin_186_newData) { // Only accept new data if the old is processed
|
||||
Plugin_186_bitpointer = 7; // reset pointer (MSB first)
|
||||
Plugin_186_bytepointer = 0; // reset pointers & flags
|
||||
Plugin_186_MasterSlave = false;
|
||||
Plugin_186_RecieveActive = true; // We are now recieving data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Plugin_046_ISR_SCLK() // Interrupt on SCLK rising
|
||||
void Plugin_186_ISR_SCLK() // Interrupt on SCLK rising
|
||||
{
|
||||
if (Plugin_046_RecieveActive) { // Are we recieving or glitch?
|
||||
if (Plugin_046_MasterSlave) { // Read MISO or MOSI?
|
||||
bitWrite(Plugin_046_recievedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MISOpin));
|
||||
if (Plugin_186_RecieveActive) { // Are we recieving or glitch?
|
||||
if (Plugin_186_MasterSlave) { // Read MISO or MOSI?
|
||||
bitWrite(Plugin_186_recievedData, Plugin_186_bitpointer, digitalRead(Plugin_186_MISOpin));
|
||||
} else {
|
||||
bitWrite(Plugin_046_recievedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MOSIpin));
|
||||
bitWrite(Plugin_186_recievedData, Plugin_186_bitpointer, digitalRead(Plugin_186_MOSIpin));
|
||||
}
|
||||
if (Plugin_046_bitpointer == 0) { // 8 bits done?
|
||||
Plugin_046_bitpointer = 7;
|
||||
if (Plugin_046_recievedData==Plugin_046_MagicByte) { // Switch data pins?
|
||||
Plugin_046_MasterSlave = true;
|
||||
if (Plugin_186_bitpointer == 0) { // 8 bits done?
|
||||
Plugin_186_bitpointer = 7;
|
||||
if (Plugin_186_recievedData==Plugin_186_MagicByte) { // Switch data pins?
|
||||
Plugin_186_MasterSlave = true;
|
||||
}
|
||||
Plugin_046_ISR_Buffer[Plugin_046_bytepointer] = Plugin_046_recievedData;
|
||||
Plugin_046_bytepointer++; // TReady for the next byte ...
|
||||
if (Plugin_046_bytepointer > Plugin_046_RAW_BUFFER_SIZE) {
|
||||
Plugin_046_RecieveActive = false; // We don't want a bufferoverflow, so abort
|
||||
Plugin_046_MasterSlave = false;
|
||||
Plugin_186_ISR_Buffer[Plugin_186_bytepointer] = Plugin_186_recievedData;
|
||||
Plugin_186_bytepointer++; // TReady for the next byte ...
|
||||
if (Plugin_186_bytepointer > Plugin_186_RAW_BUFFER_SIZE) {
|
||||
Plugin_186_RecieveActive = false; // We don't want a bufferoverflow, so abort
|
||||
Plugin_186_MasterSlave = false;
|
||||
}
|
||||
} else {
|
||||
Plugin_046_bitpointer--; // Not yet done with all bits ...
|
||||
Plugin_186_bitpointer--; // Not yet done with all bits ...
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,584 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 199: RF KaKu receiver/sender ##############################
|
||||
//#######################################################################################################
|
||||
|
||||
// Purpose: Control Klik-Aan-Klik-Uit RF 433MHz devices directly from ESP Easy (receive and send)
|
||||
// Status : "Proof of concept"
|
||||
|
||||
// Connect the RF Receiver data pin to the first pin selected in the webgui
|
||||
// Connect the RF Transmitter data pin to the second pin selected in the webgui
|
||||
|
||||
// Events:
|
||||
// newKaku_<address>#<Channel>=<state> (0=off, 1-15=dimvalue, 16=on)
|
||||
// Kaku_<address>#<Channel>=<state> (0=off, 1=on)
|
||||
// HE300EU_<address>#<Channel>=<state> (0=off, 1=on)
|
||||
|
||||
// Commands:
|
||||
// newKakuSend <address>, <Channel>, <state/dim>
|
||||
// KakuSend <address>, <Channel>, <state>
|
||||
|
||||
// This is a Work in Progress mini project!
|
||||
// It has limited use because in most cases, your fancy Home Automation controller can handle 433MHz devices quite well using RFLink.
|
||||
// It was implemented because in some cases i would like to have local "Klik-Aan-Klik-Uit" support using a standalone ESP Easy.
|
||||
// (Just because i own quite a lot of these Kaku devices)
|
||||
|
||||
// Current state / limitations:
|
||||
// Implemented send and receive support for KaKu with automatic code (no code wheel)
|
||||
// Implemented send and receive support for old KaKu unit's with code wheels
|
||||
// Implemented receive support for HomeEasy HE300EU remotes
|
||||
// RF Sender and RF receiver each need their own antenna! (as opposed to using a transceiver)
|
||||
|
||||
#define MIN_PULSE_LENGTH 100 // Too short pulses are considered to be noise...
|
||||
#define SIGNAL_TIMEOUT 5 // gap between transmissions
|
||||
#define MIN_RAW_PULSES 32 // Minimum number of pulses to be received, otherwise considered to be noise...
|
||||
#define RAW_BUFFER_SIZE 256
|
||||
#define RAWSIGNAL_MULTIPLY 25
|
||||
|
||||
void RF_ISR() ICACHE_RAM_ATTR;
|
||||
|
||||
// We need our own rawsignal buffer here.
|
||||
// During plugin rawsignal checks, the IRQ routine will alPlugin_199_ready be working on the next signal burst...
|
||||
volatile byte Plugin_199_RFBuffer[RAW_BUFFER_SIZE];
|
||||
volatile boolean Plugin_199_ready = false;
|
||||
volatile byte Plugin_199_pulses[RAW_BUFFER_SIZE + 2];
|
||||
volatile int Plugin_199_number;
|
||||
unsigned long Plugin_199_codeHash;
|
||||
unsigned long Plugin_199_lastTime;
|
||||
int8_t Plugin_199_RXpin = -1;
|
||||
int8_t Plugin_199_TXpin = -1;
|
||||
|
||||
#define PLUGIN_199
|
||||
#define PLUGIN_ID_199 199
|
||||
#define PLUGIN_NAME_199 "RF Receiver/Sender [DEVELOPMENT]"
|
||||
#define PLUGIN_VALUENAME1_199 "Address"
|
||||
#define PLUGIN_VALUENAME2_199 "Channel"
|
||||
#define PLUGIN_VALUENAME3_199 "State"
|
||||
|
||||
boolean Plugin_199(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_199;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_DUAL;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = false;
|
||||
Device[deviceCount].ValueCount = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_199);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_199));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_199));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_199));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
if (Settings.TaskDevicePin1[event->TaskIndex] != -1)
|
||||
{
|
||||
Plugin_199_RXpin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
pinMode(Plugin_199_RXpin, INPUT_PULLUP);
|
||||
attachInterrupt(Plugin_199_RXpin, RF_ISR, CHANGE);
|
||||
success = true;
|
||||
}
|
||||
if (Settings.TaskDevicePin1[event->TaskIndex] != -1)
|
||||
{
|
||||
Plugin_199_TXpin = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
pinMode(Plugin_199_TXpin, OUTPUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
if (Plugin_199_ready)
|
||||
{
|
||||
if (decodeNewKaku(event->BaseVarIndex));
|
||||
else if (decodeKaku());
|
||||
else if (decodeHE300EU());
|
||||
Plugin_199_ready = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
String command = parseString(string, 1);
|
||||
if (command == F("newkakusend"))
|
||||
{
|
||||
success = true;
|
||||
sendNewKaku(event->Par1, event->Par2, event->Par3);
|
||||
}
|
||||
if (command == F("kakusend"))
|
||||
{
|
||||
success = true;
|
||||
sendKaku(event->Par1, event->Par2, event->Par3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Interrupt handler for RF messages
|
||||
//********************************************************************************
|
||||
void RF_ISR()
|
||||
{
|
||||
static unsigned int counter = 0;
|
||||
static unsigned long TimeStamp = 0;
|
||||
unsigned long TimeElapsed = 0;
|
||||
|
||||
TimeElapsed = micros() - TimeStamp;
|
||||
TimeStamp = micros();
|
||||
|
||||
if (TimeElapsed > MIN_PULSE_LENGTH && counter < RAW_BUFFER_SIZE)
|
||||
{
|
||||
counter++;
|
||||
Plugin_199_RFBuffer[counter] = TimeElapsed / 25;
|
||||
}
|
||||
else
|
||||
counter = 0;
|
||||
|
||||
if (TimeElapsed > (SIGNAL_TIMEOUT * 1000) )
|
||||
{
|
||||
if (counter > MIN_RAW_PULSES)
|
||||
{
|
||||
Plugin_199_number = counter;
|
||||
|
||||
// copy IRQ RF working buffer to RawSignal struct
|
||||
for (unsigned int x = 0; x <= counter; x++)
|
||||
Plugin_199_pulses[x] = Plugin_199_RFBuffer[x];
|
||||
|
||||
Plugin_199_ready = true;
|
||||
counter = 0;
|
||||
}
|
||||
else
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
if (counter >= RAW_BUFFER_SIZE)
|
||||
counter = 0;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Transmit pulses using pulse array
|
||||
//********************************************************************************
|
||||
void RawSendRF(void)
|
||||
{
|
||||
if (Plugin_199_RXpin != -1)
|
||||
detachInterrupt(Plugin_199_RXpin);
|
||||
int x;
|
||||
//digitalWrite(PIN_RF_RX_VCC,LOW); // Turn off RF receiver
|
||||
//digitalWrite(PIN_RF_TX_VCC,HIGH); // Turn on RF sender
|
||||
|
||||
delay(5); // small delay between switching send/receive
|
||||
|
||||
Plugin_199_pulses[Plugin_199_number] = 1; // force last duration as 1 msec
|
||||
|
||||
for (byte y = 0; y < 7; y++) // repeats RF code
|
||||
{
|
||||
x = 1;
|
||||
noInterrupts();
|
||||
while (x < Plugin_199_number)
|
||||
{
|
||||
digitalWrite(Plugin_199_TXpin, HIGH);
|
||||
delayMicroseconds(Plugin_199_pulses[x++] * 25 - 5);
|
||||
digitalWrite(Plugin_199_TXpin, LOW);
|
||||
delayMicroseconds(Plugin_199_pulses[x++] * 25 - 7);
|
||||
}
|
||||
interrupts();
|
||||
delay(20);// Delay must run outside interrupt blocked code.
|
||||
}
|
||||
|
||||
delay(5);
|
||||
|
||||
//digitalWrite(PIN_RF_TX_VCC,LOW); // turn off RF sender
|
||||
//digitalWrite(PIN_RF_RX_VCC,HIGH); // turn on RF receiver
|
||||
if (Plugin_199_RXpin != -1)
|
||||
attachInterrupt(Plugin_199_RXpin, RF_ISR, CHANGE);
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Decode NewKaku protocol (without code wheel)
|
||||
//********************************************************************************
|
||||
#define NewKAKU_RawSignalLength 132
|
||||
#define NewKAKUdim_RawSignalLength 148
|
||||
#define NewKAKU_1T 275 // us
|
||||
#define NewKAKU_mT 650 // us
|
||||
#define NewKAKU_4T 1100 // us
|
||||
#define NewKAKU_8T 2200 // us
|
||||
|
||||
boolean decodeNewKaku(byte BaseVarIndex)
|
||||
{
|
||||
boolean success = false;
|
||||
byte Par1 = 0;
|
||||
unsigned long Par2 = 0;
|
||||
|
||||
unsigned long bitstream = 0L;
|
||||
unsigned long address = 0L;
|
||||
byte channel = 0;
|
||||
byte command = 0;
|
||||
boolean Bit;
|
||||
int i;
|
||||
int P0, P1, P2, P3;
|
||||
Par1 = 0;
|
||||
|
||||
if (Plugin_199_number == NewKAKU_RawSignalLength || Plugin_199_number == NewKAKUdim_RawSignalLength)
|
||||
{
|
||||
i = 3; // Plugin_199_pulses[3] is de eerste van een T,xT,T,xT combinatie
|
||||
|
||||
do
|
||||
{
|
||||
P0 = Plugin_199_pulses[i] * 25;
|
||||
P1 = Plugin_199_pulses[i + 1] * 25;
|
||||
P2 = Plugin_199_pulses[i + 2] * 25;
|
||||
P3 = Plugin_199_pulses[i + 3] * 25;
|
||||
|
||||
if (P0 < NewKAKU_mT && P1 < NewKAKU_mT && P2 < NewKAKU_mT && P3 > NewKAKU_mT)Bit = 0; // T,T,T,4T
|
||||
else if (P0 < NewKAKU_mT && P1 > NewKAKU_mT && P2 < NewKAKU_mT && P3 < NewKAKU_mT)Bit = 1; // T,4T,T,T
|
||||
else if (P0 < NewKAKU_mT && P1 < NewKAKU_mT && P2 < NewKAKU_mT && P3 < NewKAKU_mT) // T,T,T,T Deze hoort te zitten op i=111 want: 27e NewKAKU bit maal 4 plus 2 posities voor startbit
|
||||
{
|
||||
if (Plugin_199_number != NewKAKUdim_RawSignalLength) // als de dim-bits er niet zijn
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false; // andere mogelijkheden zijn niet geldig in NewKAKU signaal.
|
||||
|
||||
if (i < 130) // alle bits die tot de 32-bit pulstrein behoren 32bits * 4posities per bit + pulse/space voor startbit
|
||||
bitstream = (bitstream << 1) | Bit;
|
||||
else // de resterende vier bits die tot het dimlevel behoren
|
||||
Par1 = (Par1 << 1) | Bit;
|
||||
|
||||
i += 4; // volgende pulsenquartet
|
||||
} while (i < Plugin_199_number - 2); //-2 omdat de space/pulse van de stopbit geen deel meer van signaal uit maakt.
|
||||
|
||||
if (i > 140) // Commando en Dim deel
|
||||
Par1++; // Dim level. +1 omdat gebruiker dim level begint bij één.
|
||||
else
|
||||
Par1 = ((bitstream >> 4) & 0x01) ? 16 : 0; // On/Off bit omzetten naar een Nodo waarde.
|
||||
|
||||
Par2 = bitstream;
|
||||
address = bitstream >> 6;
|
||||
channel = (bitstream & 0x0f) + 1;
|
||||
command = (bitstream >> 4) & 0x03;
|
||||
if (command > 1)
|
||||
channel = 0;
|
||||
// valid signal, remember timestamp to suppress repeats...
|
||||
elapsed = millis() - Plugin_199_lastTime;
|
||||
Plugin_199_lastTime = millis();
|
||||
unsigned long codeHash = Par2 + Par1;
|
||||
if (codeHash != Plugin_199_codeHash || (codeHash == Plugin_199_codeHash && elapsed > 250))
|
||||
{
|
||||
UserVar[BaseVarIndex] = address;
|
||||
UserVar[BaseVarIndex + 1] = channel;
|
||||
UserVar[BaseVarIndex + 2] = Par1;
|
||||
String eventString = F("NewKaku_");
|
||||
eventString += address;
|
||||
eventString += F("#");
|
||||
eventString += channel;
|
||||
eventString += F("=");
|
||||
eventString += Par1;
|
||||
rulesProcessing(eventString);
|
||||
success = true;
|
||||
}
|
||||
Plugin_199_codeHash = Par2 + Par1;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Send NewKaku protocol (without code wheel)
|
||||
//********************************************************************************
|
||||
void sendNewKaku(unsigned long address, byte channel, byte state)
|
||||
{
|
||||
unsigned long bitstream = 0L;
|
||||
byte i = 1;
|
||||
byte x; // aantal posities voor pulsen/spaces in RawSignal
|
||||
|
||||
bitstream = address << 6;
|
||||
bitstream |= (channel - 1);
|
||||
|
||||
//RawSignal.Repeats = 7; // Aantal herhalingen van het signaal.
|
||||
//RawSignal.Delay = 20; // Tussen iedere pulsenreeks enige tijd rust.
|
||||
|
||||
if (state == 16 || state == 0)
|
||||
{
|
||||
bitstream |= (state == 16) << 4; // bit-5 is het on/off commando in KAKU signaal
|
||||
x = 130; // verzend startbit + 32-bits = 130
|
||||
}
|
||||
else
|
||||
x = 146; // verzend startbit + 32-bits = 130 + 4dimbits = 146
|
||||
|
||||
// bitstream bevat nu de KAKU-bits die verzonden moeten worden.
|
||||
|
||||
for (i = 3; i <= x; i++)Plugin_199_pulses[i] = NewKAKU_1T / 25; // De meeste tijden in signaal zijn T. Vul alle pulstijden met deze waarde. Later worden de 4T waarden op hun plek gezet
|
||||
|
||||
i = 1;
|
||||
Plugin_199_pulses[i++] = NewKAKU_1T / 25; //pulse van de startbit
|
||||
Plugin_199_pulses[i++] = NewKAKU_8T / 25; //space na de startbit
|
||||
|
||||
byte y = 31; // bit uit de bitstream
|
||||
while (i < x)
|
||||
{
|
||||
if ((bitstream >> (y--)) & 1)
|
||||
Plugin_199_pulses[i + 1] = NewKAKU_4T / 25; // Bit=1; // T,4T,T,T
|
||||
else
|
||||
Plugin_199_pulses[i + 3] = NewKAKU_4T / 25; // Bit=0; // T,T,T,4T
|
||||
|
||||
if (x == 146) // als het een dim opdracht betreft
|
||||
{
|
||||
if (i == 111) // Plaats van de Commando-bit uit KAKU
|
||||
Plugin_199_pulses[i + 3] = NewKAKU_1T / 25; // moet een T,T,T,T zijn bij een dim commando.
|
||||
if (i == 127) // als alle pulsen van de 32-bits weggeschreven zijn
|
||||
{
|
||||
bitstream = (unsigned long)state; // nog vier extra dim-bits om te verzenden.
|
||||
y = 3;
|
||||
}
|
||||
}
|
||||
i += 4;
|
||||
}
|
||||
Plugin_199_pulses[i++] = NewKAKU_1T / 25; //pulse van de stopbit
|
||||
Plugin_199_pulses[i] = 0; //space van de stopbit
|
||||
Plugin_199_number = i; // aantal bits*2 die zich in het opgebouwde RawSignal bevinden
|
||||
RawSendRF();
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Decode Kaku protocol (with code wheel)
|
||||
//********************************************************************************
|
||||
#define KAKU_CodeLength 12
|
||||
#define KAKU_T 350
|
||||
boolean decodeKaku()
|
||||
{
|
||||
boolean success = false;
|
||||
byte Par1 = 0;
|
||||
unsigned long Par2 = 0;
|
||||
|
||||
int i, j;
|
||||
unsigned long bitstream = 0;
|
||||
|
||||
if (Plugin_199_number != (KAKU_CodeLength * 4) + 2)return false; // conventionele KAKU bestaat altijd uit 12 data bits plus stop. Ongelijk, dan geen KAKU!
|
||||
|
||||
for (i = 0; i < KAKU_CodeLength; i++)
|
||||
{
|
||||
j = (KAKU_T * 2) / 25;
|
||||
|
||||
if (Plugin_199_pulses[4 * i + 1] < j && Plugin_199_pulses[4 * i + 2] > j && Plugin_199_pulses[4 * i + 3] < j && Plugin_199_pulses[4 * i + 4] > j) {
|
||||
bitstream = (bitstream >> 1); // 0
|
||||
}
|
||||
else if (Plugin_199_pulses[4 * i + 1] < j && Plugin_199_pulses[4 * i + 2] > j && Plugin_199_pulses[4 * i + 3] > j && Plugin_199_pulses[4 * i + 4] < j) {
|
||||
bitstream = (bitstream >> 1 | (1 << (KAKU_CodeLength - 1))); // 1
|
||||
}
|
||||
else if (Plugin_199_pulses[4 * i + 1] < j && Plugin_199_pulses[4 * i + 2] > j && Plugin_199_pulses[4 * i + 3] < j && Plugin_199_pulses[4 * i + 4] < j) {
|
||||
bitstream = (bitstream >> 1); // Short 0, Groep commando op 2e bit.
|
||||
Par1 = 2;
|
||||
}
|
||||
else {
|
||||
return false; // foutief signaal
|
||||
}
|
||||
}
|
||||
|
||||
if ((bitstream & 0x600) == 0x600) // twee vaste bits van KAKU gebruiken als checksum
|
||||
{ // Alles is in orde, bouw event op
|
||||
Par2 = bitstream & 0xFF;
|
||||
Par1 |= (bitstream >> 11) & 0x01;
|
||||
|
||||
// valid signal, remember timestamp to suppress repeats...
|
||||
elapsed = millis() - Plugin_199_lastTime;
|
||||
Plugin_199_lastTime = millis();
|
||||
unsigned long codeHash = Par2 + Par1;
|
||||
if (codeHash != Plugin_199_codeHash || (codeHash == Plugin_199_codeHash && elapsed > 250))
|
||||
{
|
||||
String eventString = F("Kaku_");
|
||||
eventString += (Par2 & 0x0f) + 1;
|
||||
eventString += F("#");
|
||||
eventString += (Par2 >> 4) + 1;
|
||||
eventString += F("=");
|
||||
eventString += Par1;
|
||||
rulesProcessing(eventString);
|
||||
success = true;
|
||||
}
|
||||
Plugin_199_codeHash = Par2 + Par1;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Send Kaku protocol (with code wheel)
|
||||
//********************************************************************************
|
||||
void sendKaku(unsigned long address, byte channel, byte state)
|
||||
{
|
||||
byte Par1 = state;
|
||||
unsigned long Par2 = ((channel-1) << 4) + address-1;
|
||||
|
||||
unsigned long Bitstream = Par2 | (0x600 | ((Par1 & 1 /*Commando*/) << 11)); // Stel een bitstream samen
|
||||
|
||||
// loop de 12-bits langs en vertaal naar pulse/space signalen.
|
||||
for (byte i = 0; i < KAKU_CodeLength; i++)
|
||||
{
|
||||
Plugin_199_pulses[4 * i + 1] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
Plugin_199_pulses[4 * i + 2] = (KAKU_T * 3) / RAWSIGNAL_MULTIPLY;
|
||||
|
||||
if (((Par1 >> 1) & 1) /* Groep */ && i >= 4 && i < 8)
|
||||
{
|
||||
Plugin_199_pulses[4 * i + 3] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
Plugin_199_pulses[4 * i + 4] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
} // short 0
|
||||
else
|
||||
{
|
||||
if ((Bitstream >> i) & 1) // 1
|
||||
{
|
||||
Plugin_199_pulses[4 * i + 3] = (KAKU_T * 3) / RAWSIGNAL_MULTIPLY;
|
||||
Plugin_199_pulses[4 * i + 4] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
}
|
||||
else //0
|
||||
{
|
||||
Plugin_199_pulses[4 * i + 3] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
Plugin_199_pulses[4 * i + 4] = (KAKU_T * 3) / RAWSIGNAL_MULTIPLY;
|
||||
}
|
||||
}
|
||||
// Stopbit
|
||||
Plugin_199_pulses[4 * KAKU_CodeLength + 1] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
Plugin_199_pulses[4 * KAKU_CodeLength + 2] = KAKU_T / RAWSIGNAL_MULTIPLY;
|
||||
}
|
||||
|
||||
Plugin_199_number=KAKU_CodeLength*4+2;
|
||||
RawSendRF();
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Decode HomeEasy 3xx series EU protocol (without code wheel)
|
||||
//********************************************************************************
|
||||
boolean decodeHE300EU()
|
||||
{
|
||||
boolean success = false;
|
||||
byte Par1 = 0;
|
||||
unsigned long Par2 = 0;
|
||||
|
||||
unsigned long address = 0;
|
||||
unsigned long bitstream = 0;
|
||||
int counter = 0;
|
||||
byte rfbit = 0;
|
||||
byte state = 0;
|
||||
unsigned long channel = 0;
|
||||
|
||||
// valid messages are 116 pulses
|
||||
if (Plugin_199_number != 116) return false;
|
||||
|
||||
for (byte x = 1; x <= Plugin_199_number; x = x + 2)
|
||||
{
|
||||
if ((Plugin_199_pulses[x] * 25 < 500) & (Plugin_199_pulses[x + 1] * 25 > 500))
|
||||
rfbit = 1;
|
||||
else
|
||||
rfbit = 0;
|
||||
|
||||
if ((x >= 23) && (x <= 86)) address = (address << 1) | rfbit;
|
||||
if ((x >= 87) && (x <= 114)) bitstream = (bitstream << 1) | rfbit;
|
||||
|
||||
}
|
||||
state = ((bitstream >> 8) & 0x3) - 1;
|
||||
channel = (bitstream) & 0x3f;
|
||||
|
||||
Par1 = state;
|
||||
Par2 = address + channel;
|
||||
|
||||
// valid signal, remember timestamp to suppress repeats...
|
||||
elapsed = millis() - Plugin_199_lastTime;
|
||||
Plugin_199_lastTime = millis();
|
||||
unsigned long codeHash = Par2 + Par1;
|
||||
if (codeHash != Plugin_199_codeHash || (codeHash == Plugin_199_codeHash && elapsed > 250))
|
||||
{
|
||||
String eventString = F("HE300EU_");
|
||||
eventString += address;
|
||||
eventString += F("#");
|
||||
eventString += channel;
|
||||
eventString += F("=");
|
||||
eventString += Par1;
|
||||
rulesProcessing(eventString);
|
||||
success = true;
|
||||
}
|
||||
Plugin_199_codeHash = Par2 + Par1;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// Decode generic protocol, deriving hash value
|
||||
//********************************************************************************
|
||||
boolean decodeUnknown()
|
||||
{
|
||||
boolean success = false;
|
||||
byte Par1 = 0;
|
||||
unsigned long Par2 = 0;
|
||||
|
||||
int x;
|
||||
unsigned int MinPulse = 0xffff;
|
||||
unsigned int MinSpace = 0xffff;
|
||||
unsigned long CodeM = 0L;
|
||||
unsigned long CodeS = 0L;
|
||||
|
||||
if (Plugin_199_number < MIN_RAW_PULSES) return false;
|
||||
|
||||
for (x = 5; x < Plugin_199_number - 2; x += 2)
|
||||
{
|
||||
if (Plugin_199_pulses[x] < MinPulse)MinPulse = Plugin_199_pulses[x];
|
||||
if (Plugin_199_pulses[x + 1] < MinSpace)MinSpace = Plugin_199_pulses[x + 1];
|
||||
}
|
||||
|
||||
MinPulse += (MinPulse * 100) / 100;
|
||||
MinSpace += (MinSpace * 100) / 100;
|
||||
|
||||
// Data kan zowel in de mark als de space zitten. Daarom pakken we beide voor data opbouw.
|
||||
for (x = 3; x <= Plugin_199_number; x += 2)
|
||||
{
|
||||
CodeM = (CodeM << 1) | (Plugin_199_pulses[x] > MinPulse);
|
||||
CodeS = (CodeS << 1) | (Plugin_199_pulses[x + 1] > MinSpace);
|
||||
}
|
||||
|
||||
// Data kan zowel in de mark als de space zitten. We nemen de grootste waarde voor de data.
|
||||
if (CodeM > CodeS)
|
||||
Par2 = CodeM;
|
||||
else
|
||||
Par2 = CodeS;
|
||||
|
||||
// valid signal, remember timestamp to suppress repeats...
|
||||
elapsed = millis() - Plugin_199_lastTime;
|
||||
Plugin_199_lastTime = millis();
|
||||
unsigned long codeHash = Par2;
|
||||
if (codeHash != Plugin_199_codeHash || (codeHash == Plugin_199_codeHash && elapsed > 250))
|
||||
{
|
||||
String eventString = F("UnknownRF_");
|
||||
eventString += Par2;
|
||||
rulesProcessing(eventString);
|
||||
success = true;
|
||||
}
|
||||
Plugin_199_codeHash = Par2;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,490 @@
|
||||
#ifdef PLUGIN_BUILD_DEV
|
||||
|
||||
//#######################################################################################################
|
||||
//#################################### Plugin 210: MQTT Import ##########################################
|
||||
//#################################### Version 0.4 5-Aug-2016 ###########################################
|
||||
//## This Version Requires ESPEasy 114+, Core 2.3 and PubSub 2.6 #######
|
||||
//#######################################################################################################
|
||||
|
||||
// This task reads data from the MQTT Import input stream and saves the value
|
||||
|
||||
#define PLUGIN_210
|
||||
#define PLUGIN_ID_210 210
|
||||
#define PLUGIN_NAME_210 "MQTT Import [DEVELOPMENT]"
|
||||
|
||||
#define PLUGIN_VALUENAME1_210 "Value1"
|
||||
#define PLUGIN_VALUENAME2_210 "Value2"
|
||||
#define PLUGIN_VALUENAME3_210 "Value3"
|
||||
#define PLUGIN_VALUENAME4_210 "Value4"
|
||||
|
||||
#define PLUGIN_IMPORT 210 // This is a 'private' function used only by this import module
|
||||
|
||||
// Declare a Wifi client for this plugin only
|
||||
|
||||
WiFiClient espclient_210;
|
||||
PubSubClient MQTTclient_210(espclient_210); // Create a new pubsub instance
|
||||
|
||||
boolean Plugin_210(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
char deviceTemplate[4][41]; // variable for saving the subscription topics
|
||||
//
|
||||
// Generate the MQTT import client name from the system name and a suffix
|
||||
//
|
||||
String tmpClientName = "%sysname%-Import";
|
||||
String ClientName = parseTemplate(tmpClientName, 20);
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_210;
|
||||
Device[deviceCount].Type = SENSOR_TYPE_SWITCH;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE; // This means it has a single pin
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true; // Need this in order to get the decimals option
|
||||
Device[deviceCount].ValueCount = 4;
|
||||
Device[deviceCount].SendDataOption = false;
|
||||
Device[deviceCount].TimerOption=false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_210);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_210));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_210));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_210));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_210));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
|
||||
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
|
||||
for (byte varNr = 0; varNr < 4; varNr++)
|
||||
{
|
||||
string += F("<TR><TD>MQTT Topic ");
|
||||
string += varNr + 1;
|
||||
string += F(":<TD><input type='text' size='40' maxlength='40' name='Plugin_210_template");
|
||||
string += varNr + 1;
|
||||
string += F("' value='");
|
||||
string += deviceTemplate[varNr];
|
||||
string += F("'>");
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
String argName;
|
||||
|
||||
for (byte varNr = 0; varNr < 4; varNr++)
|
||||
{
|
||||
argName = F("Plugin_210_template");
|
||||
argName += varNr + 1;
|
||||
strncpy(deviceTemplate[varNr], WebServer.arg(argName).c_str(), sizeof(deviceTemplate[varNr]));
|
||||
}
|
||||
|
||||
Settings.TaskDeviceID[event->TaskIndex] = 1; // temp fix, needs a dummy value
|
||||
|
||||
SaveCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
|
||||
// When we edit the subscription data from the webserver, the plugin is called again with init.
|
||||
// In order to resubscribe we have to disconnect and reconnect in order to get rid of any obsolete subscriptions
|
||||
|
||||
MQTTclient_210.disconnect();
|
||||
|
||||
if (MQTTConnect_210(ClientName))
|
||||
{
|
||||
// Subscribe to ALL the topics from ALL instance of this import module
|
||||
MQTTSubscribe_210();
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
success=false;
|
||||
}
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
MQTTclient_210.loop(); // Listen out for callbacks
|
||||
success=true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_ONCE_A_SECOND:
|
||||
{
|
||||
// Here we check that the MQTT client is alive.
|
||||
|
||||
if (!MQTTclient_210.connected()){
|
||||
|
||||
String log = F("IMPT : MQTT 210 Connection lost");
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
|
||||
MQTTclient_210.disconnect();
|
||||
delay(1000);
|
||||
|
||||
if (! MQTTConnect_210(ClientName)){
|
||||
success=false;
|
||||
break;
|
||||
}
|
||||
|
||||
MQTTSubscribe_210();
|
||||
}
|
||||
|
||||
success=true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
// This routine does not output any data and so we do not need to respond to regular read requests
|
||||
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_IMPORT:
|
||||
{
|
||||
// This is a private option only used by the MQTT 210 callback function
|
||||
|
||||
// Get the payload and check it out
|
||||
|
||||
String Payload=event->String2;
|
||||
float floatPayload=string2float(Payload);
|
||||
|
||||
LoadTaskSettings(event->TaskIndex);
|
||||
|
||||
if (floatPayload == -999){
|
||||
String log=F("IMPT : Bad Import MQTT Command ");
|
||||
log+=event->String1;
|
||||
addLog(LOG_LEVEL_ERROR,log);
|
||||
log="ERR : Illegal Payload ";
|
||||
log+=Payload;
|
||||
log+=" ";
|
||||
log+=ExtraTaskSettings.TaskDeviceName;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
success=false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the Topic and see if it matches any of the subscriptions
|
||||
|
||||
String Topic=event->String1;
|
||||
|
||||
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
|
||||
for (byte x = 0; x < 4; x++)
|
||||
{
|
||||
String subscriptionTopic = deviceTemplate[x];
|
||||
subscriptionTopic.trim();
|
||||
if (subscriptionTopic.length() == 0) continue; // skip blank subscriptions
|
||||
|
||||
// Now check if the incoming topic matches one of our subscriptions
|
||||
|
||||
if (MQTTCheckSubscription_210(Topic,subscriptionTopic))
|
||||
{
|
||||
UserVar[event->BaseVarIndex+x]=floatPayload; // Save the new value
|
||||
|
||||
// Log the event
|
||||
|
||||
String log =F("IMPT : [");
|
||||
log += ExtraTaskSettings.TaskDeviceName;
|
||||
log += F("#");
|
||||
log += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
log += F("] : ");
|
||||
log += floatPayload;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
// Generate event for rules processing - proposed by TridentTD
|
||||
|
||||
if (Settings.UseRules)
|
||||
{
|
||||
String RuleEvent = F("");
|
||||
RuleEvent += ExtraTaskSettings.TaskDeviceName;
|
||||
RuleEvent += F("#");
|
||||
RuleEvent += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
RuleEvent += F("=");
|
||||
RuleEvent += floatPayload;
|
||||
rulesProcessing(RuleEvent);
|
||||
}
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
boolean MQTTSubscribe_210()
|
||||
{
|
||||
|
||||
// Subscribe to the topics requested by ALL calls to this plugin.
|
||||
// We do this because if the connection to the broker is lost, we want to resubscribe for all instances.
|
||||
|
||||
char deviceTemplate[4][41];
|
||||
|
||||
// Loop over all tasks looking for a 210 instance
|
||||
|
||||
for (byte y = 0; y < TASKS_MAX; y++)
|
||||
{
|
||||
if (Settings.TaskDeviceNumber[y] == 210)
|
||||
{
|
||||
LoadCustomTaskSettings(y, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
|
||||
// Now loop over all import variables and subscribe to those that are not blank
|
||||
|
||||
for (byte x = 0; x < 4; x++)
|
||||
{
|
||||
String subscribeTo = deviceTemplate[x];
|
||||
|
||||
if (subscribeTo.length() > 0)
|
||||
{
|
||||
if (MQTTclient_210.subscribe(subscribeTo.c_str()))
|
||||
{
|
||||
String log = F("IMPT : [");
|
||||
LoadTaskSettings(y);
|
||||
log += ExtraTaskSettings.TaskDeviceName;
|
||||
log += F("#");
|
||||
log += ExtraTaskSettings.TaskDeviceValueNames[x];
|
||||
log += F("] subscribed to ");
|
||||
log += subscribeTo;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
else
|
||||
{
|
||||
String log = F("IMPT : Error subscribing to ");
|
||||
log += subscribeTo;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// handle MQTT messages
|
||||
//
|
||||
void mqttcallback_210(char* c_topic, byte* b_payload, unsigned int length)
|
||||
{
|
||||
// Here we have incomng MQTT messages from the mqtt import module
|
||||
|
||||
String topic = c_topic;
|
||||
|
||||
char cpayload[256];
|
||||
strncpy(cpayload, (char*)b_payload, length);
|
||||
cpayload[length] = 0;
|
||||
String payload = cpayload; // convert byte to char string
|
||||
payload.trim();
|
||||
|
||||
byte DeviceIndex = getDeviceIndex(210); // This is the device index of 210 modules -there should be one!
|
||||
|
||||
// We generate a temp event structure to pass to the plugins
|
||||
|
||||
struct EventStruct TempEvent;
|
||||
|
||||
TempEvent.String1 = topic; // This is the topic of the message
|
||||
TempEvent.String2 = payload; // This is the payload
|
||||
|
||||
// Here we loop over all tasks and call each 210 plugin with function PLUGIN_IMPORT
|
||||
|
||||
for (byte y = 0; y < TASKS_MAX; y++)
|
||||
{
|
||||
if (Settings.TaskDeviceNumber[y] == 210) // if we have found a 210 device, then give it something to think about!
|
||||
{
|
||||
TempEvent.TaskIndex = y;
|
||||
TempEvent.BaseVarIndex = y * VARS_PER_TASK; // This is the index in Uservar where values for this task are stored
|
||||
Plugin_ptr[DeviceIndex](PLUGIN_IMPORT, &TempEvent, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Make a new client connection to the mqtt broker.
|
||||
// For some reason this seems to failduring the call in INIT- however it succeeds later during recovery
|
||||
// It would be nice to understand this....
|
||||
|
||||
boolean MQTTConnect_210(String clientid)
|
||||
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
// Do nothing if already connected
|
||||
|
||||
if (MQTTclient_210.connected())return true;
|
||||
|
||||
IPAddress MQTTBrokerIP(Settings.Controller_IP);
|
||||
|
||||
// define stuff for the client - this could also be done in the intial declaration of MQTTclient_210
|
||||
|
||||
MQTTclient_210.setServer(MQTTBrokerIP, Settings.ControllerPort);
|
||||
MQTTclient_210.setCallback(mqttcallback_210);
|
||||
|
||||
// Try three times for a connection
|
||||
|
||||
for (byte x = 1; x < 4; x++)
|
||||
{
|
||||
String log = "";
|
||||
|
||||
if ((SecuritySettings.ControllerUser[0] != 0) && (SecuritySettings.ControllerPassword[0] != 0))
|
||||
result = MQTTclient_210.connect(clientid.c_str(), SecuritySettings.ControllerUser, SecuritySettings.ControllerPassword);
|
||||
else
|
||||
result = MQTTclient_210.connect(clientid.c_str());
|
||||
|
||||
|
||||
if (result)
|
||||
{
|
||||
log = F("IMPT : Connected to MQTT broker with Client ID=");
|
||||
log += clientid;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
break; // end loop if succesfull
|
||||
}
|
||||
else
|
||||
{
|
||||
log = F("IMPT : Failed to connect to MQTT broker - attempt ");
|
||||
log += x;
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
return MQTTclient_210.connected();
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if Topic matches the MQTT subscription
|
||||
//
|
||||
boolean MQTTCheckSubscription_210(String Topic, String Subscription) {
|
||||
|
||||
String tmpTopic = Topic;
|
||||
String tmpSub = Subscription;
|
||||
|
||||
tmpTopic.trim();
|
||||
tmpSub.trim();
|
||||
|
||||
// Get rid of any initial /
|
||||
|
||||
if (tmpTopic.substring(0, 1) == "/")tmpTopic = tmpTopic.substring(1);
|
||||
if (tmpSub.substring(0, 1) == "/")tmpSub = tmpSub.substring(1);
|
||||
|
||||
// Add trailing / if required
|
||||
|
||||
int lenTopic = tmpTopic.length();
|
||||
if (tmpTopic.substring(lenTopic - 1, lenTopic) != "/")tmpTopic += F("/");
|
||||
|
||||
int lenSub = tmpSub.length();
|
||||
if (tmpSub.substring(lenSub - 1, lenSub) != "/")tmpSub += F("/");
|
||||
|
||||
// Now get first part
|
||||
|
||||
int SlashTopic;
|
||||
int SlashSub;
|
||||
int count = 0;
|
||||
|
||||
String pTopic;
|
||||
String pSub;
|
||||
|
||||
while (count < 10) {
|
||||
|
||||
// Get locations of the first /
|
||||
|
||||
SlashTopic = tmpTopic.indexOf('/');
|
||||
SlashSub = tmpSub.indexOf('/');
|
||||
|
||||
// If no slashes found then match is OK
|
||||
// If only one slash found then not OK
|
||||
|
||||
if ((SlashTopic == -1) && (SlashSub == -1)) return true;
|
||||
if ((SlashTopic == -1) && (SlashSub != -1)) return false;
|
||||
if ((SlashTopic != -1) && (SlashSub == -1)) return false;
|
||||
|
||||
// Get the values for the current subtopic
|
||||
|
||||
pTopic = tmpTopic.substring(0, SlashTopic);
|
||||
pSub = tmpSub.substring(0, SlashSub);
|
||||
|
||||
// And strip the subtopic from the topic
|
||||
|
||||
tmpTopic = tmpTopic.substring(SlashTopic + 1);
|
||||
tmpSub = tmpSub.substring(SlashSub + 1);
|
||||
|
||||
// If the subtopics match then OK - otherwise fail
|
||||
if (pSub == "#") return true;
|
||||
if ((pTopic != pSub) && (pSub != "+"))return false;
|
||||
|
||||
count = count + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// Convert String to float - returns -999 in case of error
|
||||
float string2float(String myString) {
|
||||
int i, len;
|
||||
float value;
|
||||
len = myString.length();
|
||||
char tmp[(len + 1)]; // one extra for the zero termination
|
||||
byte start = 0;
|
||||
|
||||
// Look for decimal point - they can be anywhere but no more than one of them!
|
||||
|
||||
int dotIndex = myString.indexOf(".");
|
||||
//Serial.println(dotIndex);
|
||||
|
||||
if (dotIndex != -1)
|
||||
{
|
||||
int dotIndex2 = (myString.substring(dotIndex + 1)).indexOf(".");
|
||||
//Serial.println(dotIndex2);
|
||||
if (dotIndex2 != -1)return -999.00; // Give error if there is more than one dot
|
||||
}
|
||||
|
||||
if (myString.substring(0, 1) == "-") {
|
||||
start = 1; //allow a minus in front of string
|
||||
tmp[i] = '-';
|
||||
}
|
||||
|
||||
for (i = start; i<len; i++)
|
||||
{
|
||||
tmp[i] = myString.charAt(i);
|
||||
if (!isdigit(tmp[i]))
|
||||
{
|
||||
if (tmp[i] != '.')return -999;
|
||||
}
|
||||
}
|
||||
|
||||
tmp[i] = 0;
|
||||
value = atof(tmp);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1076,7 +1076,7 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
{
|
||||
for (byte y = 0; y < TASKS_MAX; y++)
|
||||
{
|
||||
if (Settings.TaskDeviceEnabled[y] && Settings.TaskDeviceNumber[y] != 0)
|
||||
if (Settings.TaskDeviceNumber[y] != 0)
|
||||
{
|
||||
for (x = 0; x < PLUGIN_MAX; x++)
|
||||
{
|
||||
@@ -1085,8 +1085,8 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[y]);
|
||||
TempEvent.TaskIndex = y;
|
||||
TempEvent.BaseVarIndex = y * VARS_PER_TASK;
|
||||
//TempEvent.idx = Settings.TaskDeviceID[y]; todo check
|
||||
TempEvent.sensorType = Device[DeviceIndex].VType;
|
||||
TempEvent.idx = Settings.TaskDeviceID[y];
|
||||
TempEvent.sensorType = Device[DeviceIndex].VType;
|
||||
if (Plugin_ptr[x](Function, event, str))
|
||||
return true;
|
||||
}
|
||||
@@ -1100,7 +1100,6 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
// Call to all plugins that are used in a task
|
||||
case PLUGIN_ONCE_A_SECOND:
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
case PLUGIN_FIFTY_PER_SECOND:
|
||||
case PLUGIN_INIT_ALL:
|
||||
case PLUGIN_CLOCK_IN:
|
||||
case PLUGIN_EVENT_OUT:
|
||||
@@ -1109,14 +1108,14 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
Function = PLUGIN_INIT;
|
||||
for (byte y = 0; y < TASKS_MAX; y++)
|
||||
{
|
||||
if (Settings.TaskDeviceEnabled[y] && Settings.TaskDeviceNumber[y] != 0)
|
||||
if (Settings.TaskDeviceNumber[y] != 0)
|
||||
{
|
||||
if (Settings.TaskDeviceDataFeed[y] == 0) // these calls only to tasks with local feed
|
||||
{
|
||||
byte DeviceIndex = getDeviceIndex(Settings.TaskDeviceNumber[y]);
|
||||
TempEvent.TaskIndex = y;
|
||||
TempEvent.BaseVarIndex = y * VARS_PER_TASK;
|
||||
//TempEvent.idx = Settings.TaskDeviceID[y]; todo check
|
||||
TempEvent.idx = Settings.TaskDeviceID[y];
|
||||
TempEvent.sensorType = Device[DeviceIndex].VType;
|
||||
TempEvent.OriginTaskIndex = event->TaskIndex;
|
||||
for (x = 0; x < PLUGIN_MAX; x++)
|
||||
@@ -1141,7 +1140,6 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
case PLUGIN_WEBFORM_SHOW_CONFIG:
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
case PLUGIN_READ:
|
||||
case PLUGIN_REMOTE_CONFIG:
|
||||
for (x = 0; x < PLUGIN_MAX; x++)
|
||||
{
|
||||
if ((Plugin_id[x] != 0 ) && (Plugin_id[x] == Settings.TaskDeviceNumber[event->TaskIndex]))
|
||||
@@ -1155,4 +1153,4 @@ byte PluginCall(byte Function, struct EventStruct *event, String& str)
|
||||
|
||||
}// case
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,6 @@
|
||||
// Rxxx 02-12-2016 EasyMega build (experimental)
|
||||
// Native SPIFFS support, old custom flash routines removed
|
||||
// Support OTA up to 1.5MB sketch size (change to 1M SPIFFS model) on 4M modules
|
||||
// Fallback Wifi AP support
|
||||
// Supports multiple active controllers
|
||||
// Supports notification plugins (basic email _N001.ino provided)
|
||||
// Native SD card support and system logging to SD card
|
||||
// Taskvalues are preserved during reboot (not after power loss!)
|
||||
// Multiple rule sets, max 4 sets, each 2k in size
|
||||
// Several device plugins reworked and added to the main branch:
|
||||
// P036 Framed OLED
|
||||
// P037 MQTT import
|
||||
// P038 NeoPixel
|
||||
// P039 Thermocouple
|
||||
// P040 ID12/RDM6300 RFID
|
||||
// P041 NeoPixel WordClock
|
||||
// P042 NeoPixel Candle
|
||||
// P043 Timer Clock
|
||||
// P044 P1 gateway
|
||||
// Removed savesettings/savecustomsettings from candle plugin, check this later...
|
||||
// UDP broadcast option prep
|
||||
// Flash write protection mechanism (aded command 'resetFlashWriteCounter')
|
||||
// IDX/var no longer mandatory and only requested when the selected controller needs it
|
||||
// Clock#Time supports 'Wrk' for workdays and 'Wkd' for weekends as wildcards
|
||||
|
||||
// R148 02-12-2016
|
||||
// Fixed a bug in ADS1115 plugin (contributed by Shardan)
|
||||
// Fixed a bug on R146 Ser2Net
|
||||
|
||||
// R147 27-11-2016
|
||||
// Fixed a situation where a large message delay uses background processing without UPD handling, causing network issues.
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION=$(git describe)
|
||||
echo "Creating release archives for $VERSION ..."
|
||||
#binaries
|
||||
# cp .pioenvs/mini_512/firmware.bin dist/"ESPEasy_$VERSION""_mini_512.bin"
|
||||
|
||||
cp .pioenvs/normal_1024/firmware.bin dist/"ESPEasy_$VERSION""_normal_1024.bin"
|
||||
cp .pioenvs/normal_4096/firmware.bin dist/"ESPEasy_$VERSION""_normal_4096.bin"
|
||||
|
||||
cp .pioenvs/test_1024/firmware.bin dist/"ESPEasy_$VERSION""_test_1024.bin"
|
||||
cp .pioenvs/test_4096/firmware.bin dist/"ESPEasy_$VERSION""_test_4096.bin"
|
||||
|
||||
cp .pioenvs/dev_1024/firmware.bin dist/"ESPEasy_$VERSION""_dev_1024.bin"
|
||||
cp .pioenvs/dev_4096/firmware.bin dist/"ESPEasy_$VERSION""_dev_4096.bin"
|
||||
|
||||
#create a source structure that is the same as the original ESPEasy project (and works with the howto on the wiki)
|
||||
rm -rf dist/Source 2>/dev/null
|
||||
mkdir dist/Source
|
||||
cp -r lib dist/Source/
|
||||
cp -r src dist/Source/
|
||||
cp platformio.ini dist/Source/
|
||||
|
||||
cd dist
|
||||
zip ../ESPEasy_$VERSION.zip -r .
|
||||
Vendored
BIN
Binary file not shown.
Vendored
-121
@@ -1,121 +0,0 @@
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev6
|
||||
-----------------------------
|
||||
|
||||
Release date: Mon Mar 13 11:54:41 CET 2017
|
||||
|
||||
Edwin Eefting (15):
|
||||
created script to assist in creating releases
|
||||
bug fix: plugin_id should not start with a 0. (compiler interprets this as octal!)
|
||||
Revert "bug fix: plugin_id should not start with a 0. (compiler interprets this as octal!)"
|
||||
bug fix: plugin_id should not start with a 0. (compiler interprets this as octal!)
|
||||
added NDIR CO2 Sensor MH-Z19 plugin to TESTING plugin set
|
||||
remove artificial sensor startup delays. (now all sensors are send immediatly after booting and wifi-connecting)
|
||||
do hardwareinit() earlier so that outputs are set immeadiatly instead of waiting for connect. fixes https://github.com/letscontrolit/ESPEasy/issues/114
|
||||
enable status light as soon as wifi is connected
|
||||
use sizeof instead of magic numbers
|
||||
Implemented speaker and tone functions from https://www.letscontrolit.com/forum/viewtopic.php?f=4&t=343&hilit=speaker&start=10
|
||||
enabled Arduino OTA for dev-firmware only, to ease developing. minor output-tweaks
|
||||
cold boot startup delay
|
||||
major change: changed the timing of the first sensor read after initial boot. cleaned up and improved deep sleeping code.
|
||||
added plugin to testing. remove useless value variable
|
||||
automaticly updated release notes for v2.0.0-dev6
|
||||
|
||||
Gerald (2):
|
||||
HTTP Advanced, enhanced, so that only one http request is sent for one sensor (#156)
|
||||
added missing sensor type, to fix problem with i2c soilmoisture sensor... (#157)
|
||||
|
||||
Jochen Krapf (1):
|
||||
cancel deep sleep loop by pulling the pin GPIO16(D0) to GND (#158)
|
||||
|
||||
dzikus (1):
|
||||
Added BMP280_CONFIG_SETTING to reduce the temperature of sensor and use oversampling filter (#155)
|
||||
|
||||
|
||||
|
||||
-----------------------------
|
||||
Changes in release v2.0.0-dev5
|
||||
-----------------------------
|
||||
|
||||
Release date: Sat Mar 11 18:15:59 CET 2017
|
||||
|
||||
DatuX (5):
|
||||
Update README.md
|
||||
Update README.md
|
||||
Update README.md
|
||||
Update README.md
|
||||
Update README.md
|
||||
|
||||
Edwin Eefting (7):
|
||||
deploy in platformio format
|
||||
simplified string handling and fixed buffer overflow
|
||||
created release notes from R148 to v2.0.0-dev4
|
||||
updated release notes for test1
|
||||
BUILD_GIT is now defined via environement variables
|
||||
use TRAVIS_TAG when building releases
|
||||
automaticly updated release notes for v2.0.0-dev5
|
||||
|
||||
Gerald (3):
|
||||
Update _P047_i2c-soil-moisture-sensor.ino
|
||||
one newline to much
|
||||
add missing features from "Generic HTTP" Plugin to "Generic HTTP Advanced" Plugin (#151)
|
||||
|
||||
Gustavo Spadari (3):
|
||||
Adding IR received code extra info
|
||||
Rename tmpString to cmdCode for clarity
|
||||
IR RAW Code implementation
|
||||
|
||||
JustMe-NL (4):
|
||||
Fix double define
|
||||
Fix Windspeed values
|
||||
Fix broken Domoticz MQTT helper
|
||||
Update WebServer.ino
|
||||
|
||||
Nonflammable (1):
|
||||
Extend functionality of P038
|
||||
|
||||
krikk (7):
|
||||
new Plugin for SoilMoisturesensor from Tindie (https://www.tindie.com/products/miceuz/i2c-soil-moisture-sensor/) minor fixes in http advanced to allow sensor type triple and http response 2xx not 200 only
|
||||
version check to detect if sensor is present, optimized address handling
|
||||
added measurement mode selection
|
||||
minor fix, shared variable name with bme280, not good :)
|
||||
variable name collision with adafruit motorshield v2 library, no functional change
|
||||
new plugin for adafruit motorshield v2, still needs a library and only support DC Motors up till now... still room for improvement
|
||||
added function to enable/disable sleep mode and version check
|
||||
|
||||
psy0rztest (1):
|
||||
Removed !echo, because its not supported in Windows.
|
||||
|
||||
|
||||
---------------------------------
|
||||
Changes in v2.0.0-dev4 since R148
|
||||
---------------------------------
|
||||
|
||||
Edwin Eefting (18):
|
||||
copy from ESPEasyMega commit 33f31e1fc3a9736266e9ee4781947d01808f88d6 but without the file renames
|
||||
bugfix in p036: pointer was not initialized to NULL
|
||||
added git version numbers output
|
||||
_C001 Sent humstat to domoticz
|
||||
fixed logging during first time initialisation
|
||||
factory reset will now always format SPIFFS. earlier boot logging
|
||||
fix factory reset by tx/rx pin double reset issue
|
||||
this was only a temporary test, forgot to remove
|
||||
turn on weblog by default
|
||||
uninitialised var
|
||||
removed systemOK: its not used anymore since SPIFFS support. (when system is not ok, it already did a resetfactory and reboots instead of continuing in emergency mode
|
||||
fixed building on systems other that platformio+linux (by making sure BUILD_GIT is defined)
|
||||
rename to .ino
|
||||
moving source files to src, in preperation of platformio directory structure
|
||||
platformio settings, travis settings, flashtools for windows, deploy script to create release .zip file
|
||||
add libraries as submodules
|
||||
add libraries we slightly modified or that i cant find the repositorys for
|
||||
new deploy key
|
||||
|
||||
JustMe-NL (6):
|
||||
Update ESPEasy.ino
|
||||
Update Misc.ino
|
||||
Update _C001.ino
|
||||
Update _C002.ino
|
||||
Create _P045_MPU6050
|
||||
Create _P046_VentusW266
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"description": "Library for the Adafruit Motor Shield V2 for Arduino. It supports DC motors & stepper motors with microstepping as well as stacking-support.",
|
||||
"repository": {
|
||||
"url": "https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library",
|
||||
"type": "git"
|
||||
},
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"atmelsam",
|
||||
"espressif8266",
|
||||
"intel_arc32",
|
||||
"microchippic32",
|
||||
"nordicnrf51",
|
||||
"teensy",
|
||||
"timsp430"
|
||||
],
|
||||
"export": {
|
||||
"exclude": [
|
||||
"extras",
|
||||
"docs",
|
||||
"tests",
|
||||
"test",
|
||||
"*.doxyfile",
|
||||
"*.pdf"
|
||||
],
|
||||
"include": null
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"maintainer": true,
|
||||
"name": "Adafruit",
|
||||
"url": null,
|
||||
"email": "info@adafruit.com"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"device",
|
||||
"control"
|
||||
],
|
||||
"id": 783,
|
||||
"name": "Adafruit Motor Shield V2 Library",
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"version": "1.0.4",
|
||||
"homepage": null
|
||||
}
|
||||
@@ -1,397 +0,0 @@
|
||||
/******************************************************************
|
||||
This is the library for the Adafruit Motor Shield V2 for Arduino.
|
||||
It supports DC motors & Stepper motors with microstepping as well
|
||||
as stacking-support. It is *not* compatible with the V1 library!
|
||||
|
||||
It will only work with https://www.adafruit.com/products/1483
|
||||
|
||||
Adafruit invests time and resources providing this open
|
||||
source code, please support Adafruit and open-source hardware
|
||||
by purchasing products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information.
|
||||
All text above must be included in any redistribution.
|
||||
******************************************************************/
|
||||
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
#include "Adafruit_MotorShield.h"
|
||||
#include <Adafruit_MS_PWMServoDriver.h>
|
||||
|
||||
#if defined(ARDUINO_SAM_DUE)
|
||||
#define WIRE Wire1
|
||||
#else
|
||||
#define WIRE Wire
|
||||
#endif
|
||||
|
||||
|
||||
#if (MICROSTEPS == 8)
|
||||
uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255};
|
||||
#elif (MICROSTEPS == 16)
|
||||
uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255};
|
||||
#endif
|
||||
|
||||
Adafruit_MotorShield::Adafruit_MotorShield(uint8_t addr) {
|
||||
_addr = addr;
|
||||
_pwm = Adafruit_MS_PWMServoDriver(_addr);
|
||||
}
|
||||
|
||||
void Adafruit_MotorShield::begin(uint16_t freq) {
|
||||
// init PWM w/_freq
|
||||
WIRE.begin();
|
||||
_pwm.begin();
|
||||
_freq = freq;
|
||||
_pwm.setPWMFreq(_freq); // This is the maximum PWM frequency
|
||||
for (uint8_t i=0; i<16; i++)
|
||||
_pwm.setPWM(i, 0, 0);
|
||||
}
|
||||
|
||||
void Adafruit_MotorShield::setPWM(uint8_t pin, uint16_t value) {
|
||||
if (value > 4095) {
|
||||
_pwm.setPWM(pin, 4096, 0);
|
||||
} else
|
||||
_pwm.setPWM(pin, 0, value);
|
||||
}
|
||||
void Adafruit_MotorShield::setPin(uint8_t pin, boolean value) {
|
||||
if (value == LOW)
|
||||
_pwm.setPWM(pin, 0, 0);
|
||||
else
|
||||
_pwm.setPWM(pin, 4096, 0);
|
||||
}
|
||||
|
||||
Adafruit_DCMotor *Adafruit_MotorShield::getMotor(uint8_t num) {
|
||||
if (num > 4) return NULL;
|
||||
|
||||
num--;
|
||||
|
||||
if (dcmotors[num].motornum == 0) {
|
||||
// not init'd yet!
|
||||
dcmotors[num].motornum = num;
|
||||
dcmotors[num].MC = this;
|
||||
uint8_t pwm, in1, in2;
|
||||
if (num == 0) {
|
||||
pwm = 8; in2 = 9; in1 = 10;
|
||||
} else if (num == 1) {
|
||||
pwm = 13; in2 = 12; in1 = 11;
|
||||
} else if (num == 2) {
|
||||
pwm = 2; in2 = 3; in1 = 4;
|
||||
} else if (num == 3) {
|
||||
pwm = 7; in2 = 6; in1 = 5;
|
||||
}
|
||||
dcmotors[num].PWMpin = pwm;
|
||||
dcmotors[num].IN1pin = in1;
|
||||
dcmotors[num].IN2pin = in2;
|
||||
}
|
||||
return &dcmotors[num];
|
||||
}
|
||||
|
||||
|
||||
Adafruit_StepperMotor *Adafruit_MotorShield::getStepper(uint16_t steps, uint8_t num) {
|
||||
if (num > 2) return NULL;
|
||||
|
||||
num--;
|
||||
|
||||
if (steppers[num].steppernum == 0) {
|
||||
// not init'd yet!
|
||||
steppers[num].steppernum = num;
|
||||
steppers[num].revsteps = steps;
|
||||
steppers[num].MC = this;
|
||||
uint8_t pwma, pwmb, ain1, ain2, bin1, bin2;
|
||||
if (num == 0) {
|
||||
pwma = 8; ain2 = 9; ain1 = 10;
|
||||
pwmb = 13; bin2 = 12; bin1 = 11;
|
||||
} else if (num == 1) {
|
||||
pwma = 2; ain2 = 3; ain1 = 4;
|
||||
pwmb = 7; bin2 = 6; bin1 = 5;
|
||||
}
|
||||
steppers[num].PWMApin = pwma;
|
||||
steppers[num].PWMBpin = pwmb;
|
||||
steppers[num].AIN1pin = ain1;
|
||||
steppers[num].AIN2pin = ain2;
|
||||
steppers[num].BIN1pin = bin1;
|
||||
steppers[num].BIN2pin = bin2;
|
||||
}
|
||||
return &steppers[num];
|
||||
}
|
||||
|
||||
|
||||
/******************************************
|
||||
MOTORS
|
||||
******************************************/
|
||||
|
||||
Adafruit_DCMotor::Adafruit_DCMotor(void) {
|
||||
MC = NULL;
|
||||
motornum = 0;
|
||||
PWMpin = IN1pin = IN2pin = 0;
|
||||
}
|
||||
|
||||
void Adafruit_DCMotor::run(uint8_t cmd) {
|
||||
switch (cmd) {
|
||||
case FORWARD:
|
||||
MC->setPin(IN2pin, LOW); // take low first to avoid 'break'
|
||||
MC->setPin(IN1pin, HIGH);
|
||||
break;
|
||||
case BACKWARD:
|
||||
MC->setPin(IN1pin, LOW); // take low first to avoid 'break'
|
||||
MC->setPin(IN2pin, HIGH);
|
||||
break;
|
||||
case RELEASE:
|
||||
MC->setPin(IN1pin, LOW);
|
||||
MC->setPin(IN2pin, LOW);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_DCMotor::setSpeed(uint8_t speed) {
|
||||
MC->setPWM(PWMpin, speed*16);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
STEPPERS
|
||||
******************************************/
|
||||
|
||||
Adafruit_StepperMotor::Adafruit_StepperMotor(void) {
|
||||
revsteps = steppernum = currentstep = 0;
|
||||
}
|
||||
/*
|
||||
|
||||
uint16_t steps, Adafruit_MotorShield controller) {
|
||||
|
||||
revsteps = steps;
|
||||
steppernum = 1;
|
||||
currentstep = 0;
|
||||
|
||||
if (steppernum == 1) {
|
||||
latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) &
|
||||
~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0
|
||||
|
||||
// enable both H bridges
|
||||
pinMode(11, OUTPUT);
|
||||
pinMode(3, OUTPUT);
|
||||
digitalWrite(11, HIGH);
|
||||
digitalWrite(3, HIGH);
|
||||
|
||||
// use PWM for microstepping support
|
||||
MC->setPWM(1, 255);
|
||||
MC->setPWM(2, 255);
|
||||
|
||||
} else if (steppernum == 2) {
|
||||
latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) &
|
||||
~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // all motor pins to 0
|
||||
|
||||
// enable both H bridges
|
||||
pinMode(5, OUTPUT);
|
||||
pinMode(6, OUTPUT);
|
||||
digitalWrite(5, HIGH);
|
||||
digitalWrite(6, HIGH);
|
||||
|
||||
// use PWM for microstepping support
|
||||
// use PWM for microstepping support
|
||||
MC->setPWM(3, 255);
|
||||
MC->setPWM(4, 255);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Adafruit_StepperMotor::setSpeed(uint16_t rpm) {
|
||||
//Serial.println("steps per rev: "); Serial.println(revsteps);
|
||||
//Serial.println("RPM: "); Serial.println(rpm);
|
||||
|
||||
usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm);
|
||||
}
|
||||
|
||||
void Adafruit_StepperMotor::release(void) {
|
||||
MC->setPin(AIN1pin, LOW);
|
||||
MC->setPin(AIN2pin, LOW);
|
||||
MC->setPin(BIN1pin, LOW);
|
||||
MC->setPin(BIN2pin, LOW);
|
||||
MC->setPWM(PWMApin, 0);
|
||||
MC->setPWM(PWMBpin, 0);
|
||||
}
|
||||
|
||||
void Adafruit_StepperMotor::step(uint16_t steps, uint8_t dir, uint8_t style) {
|
||||
uint32_t uspers = usperstep;
|
||||
uint8_t ret = 0;
|
||||
|
||||
if (style == INTERLEAVE) {
|
||||
uspers /= 2;
|
||||
}
|
||||
else if (style == MICROSTEP) {
|
||||
uspers /= MICROSTEPS;
|
||||
steps *= MICROSTEPS;
|
||||
#ifdef MOTORDEBUG
|
||||
Serial.print("steps = "); Serial.println(steps, DEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
while (steps--) {
|
||||
//Serial.println("step!"); Serial.println(uspers);
|
||||
ret = onestep(dir, style);
|
||||
delayMicroseconds(uspers);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Adafruit_StepperMotor::onestep(uint8_t dir, uint8_t style) {
|
||||
uint8_t a, b, c, d;
|
||||
uint8_t ocrb, ocra;
|
||||
|
||||
ocra = ocrb = 255;
|
||||
|
||||
|
||||
// next determine what sort of stepping procedure we're up to
|
||||
if (style == SINGLE) {
|
||||
if ((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird
|
||||
if (dir == FORWARD) {
|
||||
currentstep += MICROSTEPS/2;
|
||||
}
|
||||
else {
|
||||
currentstep -= MICROSTEPS/2;
|
||||
}
|
||||
} else { // go to the next even step
|
||||
if (dir == FORWARD) {
|
||||
currentstep += MICROSTEPS;
|
||||
}
|
||||
else {
|
||||
currentstep -= MICROSTEPS;
|
||||
}
|
||||
}
|
||||
} else if (style == DOUBLE) {
|
||||
if (! (currentstep/(MICROSTEPS/2) % 2)) { // we're at an even step, weird
|
||||
if (dir == FORWARD) {
|
||||
currentstep += MICROSTEPS/2;
|
||||
} else {
|
||||
currentstep -= MICROSTEPS/2;
|
||||
}
|
||||
} else { // go to the next odd step
|
||||
if (dir == FORWARD) {
|
||||
currentstep += MICROSTEPS;
|
||||
} else {
|
||||
currentstep -= MICROSTEPS;
|
||||
}
|
||||
}
|
||||
} else if (style == INTERLEAVE) {
|
||||
if (dir == FORWARD) {
|
||||
currentstep += MICROSTEPS/2;
|
||||
} else {
|
||||
currentstep -= MICROSTEPS/2;
|
||||
}
|
||||
}
|
||||
|
||||
if (style == MICROSTEP) {
|
||||
if (dir == FORWARD) {
|
||||
currentstep++;
|
||||
} else {
|
||||
// BACKWARDS
|
||||
currentstep--;
|
||||
}
|
||||
|
||||
currentstep += MICROSTEPS*4;
|
||||
currentstep %= MICROSTEPS*4;
|
||||
|
||||
ocra = ocrb = 0;
|
||||
if ( (currentstep >= 0) && (currentstep < MICROSTEPS)) {
|
||||
ocra = microstepcurve[MICROSTEPS - currentstep];
|
||||
ocrb = microstepcurve[currentstep];
|
||||
} else if ( (currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) {
|
||||
ocra = microstepcurve[currentstep - MICROSTEPS];
|
||||
ocrb = microstepcurve[MICROSTEPS*2 - currentstep];
|
||||
} else if ( (currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) {
|
||||
ocra = microstepcurve[MICROSTEPS*3 - currentstep];
|
||||
ocrb = microstepcurve[currentstep - MICROSTEPS*2];
|
||||
} else if ( (currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) {
|
||||
ocra = microstepcurve[currentstep - MICROSTEPS*3];
|
||||
ocrb = microstepcurve[MICROSTEPS*4 - currentstep];
|
||||
}
|
||||
}
|
||||
|
||||
currentstep += MICROSTEPS*4;
|
||||
currentstep %= MICROSTEPS*4;
|
||||
|
||||
#ifdef MOTORDEBUG
|
||||
Serial.print("current step: "); Serial.println(currentstep, DEC);
|
||||
Serial.print(" pwmA = "); Serial.print(ocra, DEC);
|
||||
Serial.print(" pwmB = "); Serial.println(ocrb, DEC);
|
||||
#endif
|
||||
MC->setPWM(PWMApin, ocra*16);
|
||||
MC->setPWM(PWMBpin, ocrb*16);
|
||||
|
||||
|
||||
// release all
|
||||
uint8_t latch_state = 0; // all motor pins to 0
|
||||
|
||||
//Serial.println(step, DEC);
|
||||
if (style == MICROSTEP) {
|
||||
if ((currentstep >= 0) && (currentstep < MICROSTEPS))
|
||||
latch_state |= 0x03;
|
||||
if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2))
|
||||
latch_state |= 0x06;
|
||||
if ((currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3))
|
||||
latch_state |= 0x0C;
|
||||
if ((currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4))
|
||||
latch_state |= 0x09;
|
||||
} else {
|
||||
switch (currentstep/(MICROSTEPS/2)) {
|
||||
case 0:
|
||||
latch_state |= 0x1; // energize coil 1 only
|
||||
break;
|
||||
case 1:
|
||||
latch_state |= 0x3; // energize coil 1+2
|
||||
break;
|
||||
case 2:
|
||||
latch_state |= 0x2; // energize coil 2 only
|
||||
break;
|
||||
case 3:
|
||||
latch_state |= 0x6; // energize coil 2+3
|
||||
break;
|
||||
case 4:
|
||||
latch_state |= 0x4; // energize coil 3 only
|
||||
break;
|
||||
case 5:
|
||||
latch_state |= 0xC; // energize coil 3+4
|
||||
break;
|
||||
case 6:
|
||||
latch_state |= 0x8; // energize coil 4 only
|
||||
break;
|
||||
case 7:
|
||||
latch_state |= 0x9; // energize coil 1+4
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef MOTORDEBUG
|
||||
Serial.print("Latch: 0x"); Serial.println(latch_state, HEX);
|
||||
#endif
|
||||
|
||||
if (latch_state & 0x1) {
|
||||
// Serial.println(AIN2pin);
|
||||
MC->setPin(AIN2pin, HIGH);
|
||||
} else {
|
||||
MC->setPin(AIN2pin, LOW);
|
||||
}
|
||||
if (latch_state & 0x2) {
|
||||
MC->setPin(BIN1pin, HIGH);
|
||||
// Serial.println(BIN1pin);
|
||||
} else {
|
||||
MC->setPin(BIN1pin, LOW);
|
||||
}
|
||||
if (latch_state & 0x4) {
|
||||
MC->setPin(AIN1pin, HIGH);
|
||||
// Serial.println(AIN1pin);
|
||||
} else {
|
||||
MC->setPin(AIN1pin, LOW);
|
||||
}
|
||||
if (latch_state & 0x8) {
|
||||
MC->setPin(BIN2pin, HIGH);
|
||||
// Serial.println(BIN2pin);
|
||||
} else {
|
||||
MC->setPin(BIN2pin, LOW);
|
||||
}
|
||||
|
||||
return currentstep;
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/******************************************************************
|
||||
This is the library for the Adafruit Motor Shield V2 for Arduino.
|
||||
It supports DC motors & Stepper motors with microstepping as well
|
||||
as stacking-support. It is *not* compatible with the V1 library!
|
||||
|
||||
It will only work with https://www.adafruit.com/products/1483
|
||||
|
||||
Adafruit invests time and resources providing this open
|
||||
source code, please support Adafruit and open-source hardware
|
||||
by purchasing products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information.
|
||||
All text above must be included in any redistribution.
|
||||
******************************************************************/
|
||||
|
||||
#ifndef _Adafruit_MotorShield_h_
|
||||
#define _Adafruit_MotorShield_h_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Wire.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
//#define MOTORDEBUG
|
||||
|
||||
#define MICROSTEPS 16 // 8 or 16
|
||||
|
||||
#define MOTOR1_A 2
|
||||
#define MOTOR1_B 3
|
||||
#define MOTOR2_A 1
|
||||
#define MOTOR2_B 4
|
||||
#define MOTOR4_A 0
|
||||
#define MOTOR4_B 6
|
||||
#define MOTOR3_A 5
|
||||
#define MOTOR3_B 7
|
||||
|
||||
#define FORWARD 1
|
||||
#define BACKWARD 2
|
||||
#define BRAKE 3
|
||||
#define RELEASE 4
|
||||
|
||||
#define SINGLE 1
|
||||
#define DOUBLE 2
|
||||
#define INTERLEAVE 3
|
||||
#define MICROSTEP 4
|
||||
|
||||
class Adafruit_MotorShield;
|
||||
|
||||
class Adafruit_DCMotor
|
||||
{
|
||||
public:
|
||||
Adafruit_DCMotor(void);
|
||||
friend class Adafruit_MotorShield;
|
||||
void run(uint8_t);
|
||||
void setSpeed(uint8_t);
|
||||
|
||||
private:
|
||||
uint8_t PWMpin, IN1pin, IN2pin;
|
||||
Adafruit_MotorShield *MC;
|
||||
uint8_t motornum;
|
||||
};
|
||||
|
||||
class Adafruit_StepperMotor {
|
||||
public:
|
||||
Adafruit_StepperMotor(void);
|
||||
friend class Adafruit_MotorShield;
|
||||
|
||||
void step(uint16_t steps, uint8_t dir, uint8_t style = SINGLE);
|
||||
void setSpeed(uint16_t);
|
||||
uint8_t onestep(uint8_t dir, uint8_t style);
|
||||
void release(void);
|
||||
uint32_t usperstep;
|
||||
|
||||
private:
|
||||
uint8_t PWMApin, AIN1pin, AIN2pin;
|
||||
uint8_t PWMBpin, BIN1pin, BIN2pin;
|
||||
uint16_t revsteps; // # steps per revolution
|
||||
uint8_t currentstep;
|
||||
Adafruit_MotorShield *MC;
|
||||
uint8_t steppernum;
|
||||
};
|
||||
|
||||
class Adafruit_MotorShield
|
||||
{
|
||||
public:
|
||||
Adafruit_MotorShield(uint8_t addr = 0x60);
|
||||
friend class Adafruit_DCMotor;
|
||||
void begin(uint16_t freq = 1600);
|
||||
|
||||
void setPWM(uint8_t pin, uint16_t val);
|
||||
void setPin(uint8_t pin, boolean val);
|
||||
Adafruit_DCMotor *getMotor(uint8_t n);
|
||||
Adafruit_StepperMotor *getStepper(uint16_t steps, uint8_t n);
|
||||
private:
|
||||
uint8_t _addr;
|
||||
uint16_t _freq;
|
||||
Adafruit_DCMotor dcmotors[4];
|
||||
Adafruit_StepperMotor steppers[2];
|
||||
Adafruit_MS_PWMServoDriver _pwm;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
# Adafruit Motor Shield v2 Library
|
||||
|
||||
This is the library for the Adafruit Motor Shield V2 for Arduino.
|
||||
It supports DC motors & Stepper motors with microstepping as well
|
||||
as stacking-support. It is *not* compatible with the V1 library!
|
||||
|
||||
It will only work with https://www.adafruit.com/products/1438
|
||||
|
||||
<!-- START COMPATIBILITY TABLE -->
|
||||
|
||||
## Compatibility
|
||||
|
||||
MCU | Tested Works | Doesn't Work | Not Tested | Notes
|
||||
----------------- | :----------: | :----------: | :---------: | -----
|
||||
Atmega328 @ 16MHz | X | | |
|
||||
Atmega328 @ 12MHz | X | | |
|
||||
Atmega32u4 @ 16MHz | X | | |
|
||||
Atmega32u4 @ 8MHz | X | | |
|
||||
ESP8266 | | | X |
|
||||
Atmega2560 @ 16MHz | X | | |
|
||||
ATSAM3X8E | | X | |
|
||||
ATSAM21D | | X | |
|
||||
ATtiny85 @ 16MHz | | | X |
|
||||
ATtiny85 @ 8MHz | | | X |
|
||||
|
||||
* ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
|
||||
* ATmega328 @ 12MHz : Adafruit Pro Trinket 3V
|
||||
* ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0
|
||||
* ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro
|
||||
* ESP8266 : Adafruit Huzzah
|
||||
* ATmega2560 @ 16MHz : Arduino Mega
|
||||
* ATSAM3X8E : Arduino Due
|
||||
* ATSAM21D : Arduino Zero, M0 Pro
|
||||
* ATtiny85 @ 16MHz : Adafruit Trinket 5V
|
||||
* ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V
|
||||
|
||||
<!-- END COMPATIBILITY TABLE -->
|
||||
|
||||
Adafruit invests time and resources providing this open
|
||||
source code, please support Adafruit and open-source hardware
|
||||
by purchasing products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, check license.txt for more information.
|
||||
All text above must be included in any redistribution.
|
||||
@@ -1,52 +0,0 @@
|
||||
// ConstantSpeed.pde
|
||||
// -*- mode: C++ -*-
|
||||
//
|
||||
// Shows how to run AccelStepper in the simplest,
|
||||
// fixed speed mode with no accelerations
|
||||
// Requires the Adafruit_Motorshield v2 library
|
||||
// https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
|
||||
// And AccelStepper with AFMotor support
|
||||
// https://github.com/adafruit/AccelStepper
|
||||
|
||||
// This tutorial is for Adafruit Motorshield v2 only!
|
||||
// Will not work with v1 shields
|
||||
|
||||
#include <AccelStepper.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
// Create the motor shield object with the default I2C address
|
||||
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
|
||||
// Or, create it with a different I2C address (say for stacking)
|
||||
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
|
||||
|
||||
// Connect a stepper motor with 200 steps per revolution (1.8 degree)
|
||||
// to motor port #2 (M3 and M4)
|
||||
Adafruit_StepperMotor *myStepper1 = AFMS.getStepper(200, 2);
|
||||
|
||||
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
|
||||
void forwardstep1() {
|
||||
myStepper1->onestep(FORWARD, SINGLE);
|
||||
}
|
||||
void backwardstep1() {
|
||||
myStepper1->onestep(BACKWARD, SINGLE);
|
||||
}
|
||||
|
||||
AccelStepper Astepper1(forwardstep1, backwardstep1); // use functions to step
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600); // set up Serial library at 9600 bps
|
||||
Serial.println("Stepper test!");
|
||||
|
||||
AFMS.begin(); // create with the default frequency 1.6KHz
|
||||
//AFMS.begin(1000); // OR with a different frequency, say 1KHz
|
||||
|
||||
Astepper1.setSpeed(50);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Astepper1.runSpeed();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
// Shows how to run three Steppers at once with varying speeds
|
||||
//
|
||||
// Requires the Adafruit_Motorshield v2 library
|
||||
// https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
|
||||
// And AccelStepper with AFMotor support
|
||||
// https://github.com/adafruit/AccelStepper
|
||||
|
||||
// This tutorial is for Adafruit Motorshield v2 only!
|
||||
// Will not work with v1 shields
|
||||
|
||||
#include <AccelStepper.h>
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed
|
||||
Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers
|
||||
|
||||
// Connect two steppers with 200 steps per revolution (1.8 degree)
|
||||
// to the top shield
|
||||
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
|
||||
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);
|
||||
|
||||
// Connect one stepper with 200 steps per revolution (1.8 degree)
|
||||
// to the bottom shield
|
||||
Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(200, 2);
|
||||
|
||||
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
|
||||
// wrappers for the first motor!
|
||||
void forwardstep1() {
|
||||
myStepper1->onestep(FORWARD, SINGLE);
|
||||
}
|
||||
void backwardstep1() {
|
||||
myStepper1->onestep(BACKWARD, SINGLE);
|
||||
}
|
||||
// wrappers for the second motor!
|
||||
void forwardstep2() {
|
||||
myStepper2->onestep(FORWARD, DOUBLE);
|
||||
}
|
||||
void backwardstep2() {
|
||||
myStepper2->onestep(BACKWARD, DOUBLE);
|
||||
}
|
||||
// wrappers for the third motor!
|
||||
void forwardstep3() {
|
||||
myStepper3->onestep(FORWARD, INTERLEAVE);
|
||||
}
|
||||
void backwardstep3() {
|
||||
myStepper3->onestep(BACKWARD, INTERLEAVE);
|
||||
}
|
||||
|
||||
// Now we'll wrap the 3 steppers in an AccelStepper object
|
||||
AccelStepper stepper1(forwardstep1, backwardstep1);
|
||||
AccelStepper stepper2(forwardstep2, backwardstep2);
|
||||
AccelStepper stepper3(forwardstep3, backwardstep3);
|
||||
|
||||
void setup()
|
||||
{
|
||||
AFMSbot.begin(); // Start the bottom shield
|
||||
AFMStop.begin(); // Start the top shield
|
||||
|
||||
stepper1.setMaxSpeed(100.0);
|
||||
stepper1.setAcceleration(100.0);
|
||||
stepper1.moveTo(24);
|
||||
|
||||
stepper2.setMaxSpeed(200.0);
|
||||
stepper2.setAcceleration(100.0);
|
||||
stepper2.moveTo(50000);
|
||||
|
||||
stepper3.setMaxSpeed(300.0);
|
||||
stepper3.setAcceleration(100.0);
|
||||
stepper3.moveTo(1000000);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Change direction at the limits
|
||||
if (stepper1.distanceToGo() == 0)
|
||||
stepper1.moveTo(-stepper1.currentPosition());
|
||||
|
||||
if (stepper2.distanceToGo() == 0)
|
||||
stepper2.moveTo(-stepper2.currentPosition());
|
||||
|
||||
if (stepper3.distanceToGo() == 0)
|
||||
stepper3.moveTo(-stepper3.currentPosition());
|
||||
|
||||
stepper1.run();
|
||||
stepper2.run();
|
||||
stepper3.run();
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
|
||||
It won't work with v1.x motor shields! Only for the v2's with built in PWM
|
||||
control
|
||||
|
||||
For use with the Adafruit Motor Shield v2
|
||||
----> http://www.adafruit.com/products/1438
|
||||
*/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
// Create the motor shield object with the default I2C address
|
||||
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
|
||||
// Or, create it with a different I2C address (say for stacking)
|
||||
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
|
||||
|
||||
// Select which 'port' M1, M2, M3 or M4. In this case, M1
|
||||
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
|
||||
// You can also make another motor on port M2
|
||||
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600); // set up Serial library at 9600 bps
|
||||
Serial.println("Adafruit Motorshield v2 - DC Motor test!");
|
||||
|
||||
AFMS.begin(); // create with the default frequency 1.6KHz
|
||||
//AFMS.begin(1000); // OR with a different frequency, say 1KHz
|
||||
|
||||
// Set the speed to start, from 0 (off) to 255 (max speed)
|
||||
myMotor->setSpeed(150);
|
||||
myMotor->run(FORWARD);
|
||||
// turn on motor
|
||||
myMotor->run(RELEASE);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint8_t i;
|
||||
|
||||
Serial.print("tick");
|
||||
|
||||
myMotor->run(FORWARD);
|
||||
for (i=0; i<255; i++) {
|
||||
myMotor->setSpeed(i);
|
||||
delay(10);
|
||||
}
|
||||
for (i=255; i!=0; i--) {
|
||||
myMotor->setSpeed(i);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Serial.print("tock");
|
||||
|
||||
myMotor->run(BACKWARD);
|
||||
for (i=0; i<255; i++) {
|
||||
myMotor->setSpeed(i);
|
||||
delay(10);
|
||||
}
|
||||
for (i=255; i!=0; i--) {
|
||||
myMotor->setSpeed(i);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Serial.print("tech");
|
||||
myMotor->run(RELEASE);
|
||||
delay(1000);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
|
||||
It won't work with v1.x motor shields! Only for the v2's with built in PWM
|
||||
control
|
||||
|
||||
For use with the Adafruit Motor Shield v2
|
||||
----> http://www.adafruit.com/products/1438
|
||||
|
||||
This sketch creates a fun motor party on your desk *whiirrr*
|
||||
Connect a unipolar/bipolar stepper to M3/M4
|
||||
Connect a DC motor to M1
|
||||
Connect a hobby servo to SERVO1
|
||||
*/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
#include <Servo.h>
|
||||
|
||||
// Create the motor shield object with the default I2C address
|
||||
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
|
||||
// Or, create it with a different I2C address (say for stacking)
|
||||
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
|
||||
|
||||
// Connect a stepper motor with 200 steps per revolution (1.8 degree)
|
||||
// to motor port #2 (M3 and M4)
|
||||
Adafruit_StepperMotor *myStepper = AFMS.getStepper(200, 2);
|
||||
// And connect a DC motor to port M1
|
||||
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
|
||||
|
||||
// We'll also test out the built in Arduino Servo library
|
||||
Servo servo1;
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600); // set up Serial library at 9600 bps
|
||||
Serial.println("MMMMotor party!");
|
||||
|
||||
AFMS.begin(); // create with the default frequency 1.6KHz
|
||||
//AFMS.begin(1000); // OR with a different frequency, say 1KHz
|
||||
|
||||
// Attach a servo to pin #10
|
||||
servo1.attach(10);
|
||||
|
||||
// turn on motor M1
|
||||
myMotor->setSpeed(200);
|
||||
myMotor->run(RELEASE);
|
||||
|
||||
// setup the stepper
|
||||
myStepper->setSpeed(10); // 10 rpm
|
||||
}
|
||||
|
||||
int i;
|
||||
void loop() {
|
||||
myMotor->run(FORWARD);
|
||||
for (i=0; i<255; i++) {
|
||||
servo1.write(map(i, 0, 255, 0, 180));
|
||||
myMotor->setSpeed(i);
|
||||
myStepper->step(1, FORWARD, INTERLEAVE);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
for (i=255; i!=0; i--) {
|
||||
servo1.write(map(i, 0, 255, 0, 180));
|
||||
myMotor->setSpeed(i);
|
||||
myStepper->step(1, BACKWARD, INTERLEAVE);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
myMotor->run(BACKWARD);
|
||||
for (i=0; i<255; i++) {
|
||||
servo1.write(map(i, 0, 255, 0, 180));
|
||||
myMotor->setSpeed(i);
|
||||
myStepper->step(1, FORWARD, DOUBLE);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
for (i=255; i!=0; i--) {
|
||||
servo1.write(map(i, 0, 255, 0, 180));
|
||||
myMotor->setSpeed(i);
|
||||
myStepper->step(1, BACKWARD, DOUBLE);
|
||||
delay(3);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
|
||||
It won't work with v1.x motor shields! Only for the v2's with built in PWM
|
||||
control
|
||||
|
||||
For use with the Adafruit Motor Shield v2
|
||||
----> http://www.adafruit.com/products/1438
|
||||
*/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed
|
||||
Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers
|
||||
|
||||
// On the top shield, connect two steppers, each with 200 steps
|
||||
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 1);
|
||||
Adafruit_StepperMotor *myStepper3 = AFMStop.getStepper(200, 2);
|
||||
|
||||
// On the bottom shield connect a stepper to port M3/M4 with 200 steps
|
||||
Adafruit_StepperMotor *myStepper1 = AFMSbot.getStepper(200, 2);
|
||||
// And a DC Motor to port M1
|
||||
Adafruit_DCMotor *myMotor1 = AFMSbot.getMotor(1);
|
||||
|
||||
void setup() {
|
||||
while (!Serial);
|
||||
Serial.begin(9600); // set up Serial library at 9600 bps
|
||||
Serial.println("MMMMotor party!");
|
||||
|
||||
AFMSbot.begin(); // Start the bottom shield
|
||||
AFMStop.begin(); // Start the top shield
|
||||
|
||||
// turn on the DC motor
|
||||
myMotor1->setSpeed(200);
|
||||
myMotor1->run(RELEASE);
|
||||
}
|
||||
|
||||
int i;
|
||||
void loop() {
|
||||
myMotor1->run(FORWARD);
|
||||
|
||||
for (i=0; i<255; i++) {
|
||||
myMotor1->setSpeed(i);
|
||||
myStepper1->onestep(FORWARD, INTERLEAVE);
|
||||
myStepper2->onestep(BACKWARD, DOUBLE);
|
||||
myStepper3->onestep(FORWARD, MICROSTEP);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
for (i=255; i!=0; i--) {
|
||||
myMotor1->setSpeed(i);
|
||||
myStepper1->onestep(BACKWARD, INTERLEAVE);
|
||||
myStepper2->onestep(FORWARD, DOUBLE);
|
||||
myStepper3->onestep(BACKWARD, MICROSTEP);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
myMotor1->run(BACKWARD);
|
||||
|
||||
for (i=0; i<255; i++) {
|
||||
myMotor1->setSpeed(i);
|
||||
myStepper1->onestep(FORWARD, DOUBLE);
|
||||
myStepper2->onestep(BACKWARD, INTERLEAVE);
|
||||
myStepper3->onestep(FORWARD, MICROSTEP);
|
||||
delay(3);
|
||||
}
|
||||
|
||||
for (i=255; i!=0; i--) {
|
||||
myMotor1->setSpeed(i);
|
||||
myStepper1->onestep(BACKWARD, DOUBLE);
|
||||
myStepper2->onestep(FORWARD, INTERLEAVE);
|
||||
myStepper3->onestep(BACKWARD, MICROSTEP);
|
||||
delay(3);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
|
||||
It won't work with v1.x motor shields! Only for the v2's with built in PWM
|
||||
control
|
||||
|
||||
For use with the Adafruit Motor Shield v2
|
||||
----> http://www.adafruit.com/products/1438
|
||||
*/
|
||||
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_MotorShield.h>
|
||||
#include "utility/Adafruit_MS_PWMServoDriver.h"
|
||||
|
||||
// Create the motor shield object with the default I2C address
|
||||
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
|
||||
// Or, create it with a different I2C address (say for stacking)
|
||||
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);
|
||||
|
||||
// Connect a stepper motor with 200 steps per revolution (1.8 degree)
|
||||
// to motor port #2 (M3 and M4)
|
||||
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600); // set up Serial library at 9600 bps
|
||||
Serial.println("Stepper test!");
|
||||
|
||||
AFMS.begin(); // create with the default frequency 1.6KHz
|
||||
//AFMS.begin(1000); // OR with a different frequency, say 1KHz
|
||||
|
||||
myMotor->setSpeed(10); // 10 rpm
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("Single coil steps");
|
||||
myMotor->step(100, FORWARD, SINGLE);
|
||||
myMotor->step(100, BACKWARD, SINGLE);
|
||||
|
||||
Serial.println("Double coil steps");
|
||||
myMotor->step(100, FORWARD, DOUBLE);
|
||||
myMotor->step(100, BACKWARD, DOUBLE);
|
||||
|
||||
Serial.println("Interleave coil steps");
|
||||
myMotor->step(100, FORWARD, INTERLEAVE);
|
||||
myMotor->step(100, BACKWARD, INTERLEAVE);
|
||||
|
||||
Serial.println("Microstep steps");
|
||||
myMotor->step(50, FORWARD, MICROSTEP);
|
||||
myMotor->step(50, BACKWARD, MICROSTEP);
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for AFMotor
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Adafruit_MotorShield KEYWORD1
|
||||
Adafruit_DCMotor KEYWORD1
|
||||
Adafruit_StepperMotor KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
enable KEYWORD2
|
||||
run KEYWORD2
|
||||
setSpeed KEYWORD2
|
||||
step KEYWORD2
|
||||
onestep KEYWORD2
|
||||
release KEYWORD2
|
||||
getMotor KEYWORD2
|
||||
getStepper KEYWORD2
|
||||
setPin KEYWORD2
|
||||
setPWM KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
MICROSTEPPING LITERAL1
|
||||
FORWARD LITERAL1
|
||||
BACKWARD LITERAL1
|
||||
BRAKE LITERAL1
|
||||
RELEASE LITERAL1
|
||||
SINGLE LITERAL1
|
||||
DOUBLE LITERAL1
|
||||
INTERLEAVE LITERAL1
|
||||
MICROSTEP LITERAL1
|
||||
@@ -1,9 +0,0 @@
|
||||
name=Adafruit Motor Shield V2 Library
|
||||
version=1.0.4
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Library for the Adafruit Motor Shield V2 for Arduino. It supports DC motors & stepper motors with microstepping as well as stacking-support.
|
||||
paragraph=Library for the Adafruit Motor Shield V2 for Arduino. It supports DC motors & stepper motors with microstepping as well as stacking-support.
|
||||
category=Device Control
|
||||
url=https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
|
||||
architectures=*
|
||||
@@ -1,25 +0,0 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2012, Adafruit Industries. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,113 +0,0 @@
|
||||
/***************************************************
|
||||
This is a library for our Adafruit 16-channel PWM & Servo driver
|
||||
|
||||
Pick one up today in the adafruit shop!
|
||||
------> http://www.adafruit.com/products/815
|
||||
|
||||
These displays use I2C to communicate, 2 pins are required to
|
||||
interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include <Adafruit_MS_PWMServoDriver.h>
|
||||
#include <Wire.h>
|
||||
#if defined(ARDUINO_SAM_DUE)
|
||||
#define WIRE Wire1
|
||||
#else
|
||||
#define WIRE Wire
|
||||
#endif
|
||||
|
||||
|
||||
Adafruit_MS_PWMServoDriver::Adafruit_MS_PWMServoDriver(uint8_t addr) {
|
||||
_i2caddr = addr;
|
||||
}
|
||||
|
||||
void Adafruit_MS_PWMServoDriver::begin(void) {
|
||||
WIRE.begin();
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_MS_PWMServoDriver::reset(void) {
|
||||
write8(PCA9685_MODE1, 0x0);
|
||||
}
|
||||
|
||||
void Adafruit_MS_PWMServoDriver::setPWMFreq(float freq) {
|
||||
//Serial.print("Attempting to set freq ");
|
||||
//Serial.println(freq);
|
||||
|
||||
freq *= 0.9; // Correct for overshoot in the frequency setting (see issue #11).
|
||||
|
||||
float prescaleval = 25000000;
|
||||
prescaleval /= 4096;
|
||||
prescaleval /= freq;
|
||||
prescaleval -= 1;
|
||||
//Serial.print("Estimated pre-scale: "); Serial.println(prescaleval);
|
||||
uint8_t prescale = floor(prescaleval + 0.5);
|
||||
//Serial.print("Final pre-scale: "); Serial.println(prescale);
|
||||
|
||||
uint8_t oldmode = read8(PCA9685_MODE1);
|
||||
uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep
|
||||
write8(PCA9685_MODE1, newmode); // go to sleep
|
||||
write8(PCA9685_PRESCALE, prescale); // set the prescaler
|
||||
write8(PCA9685_MODE1, oldmode);
|
||||
delay(5);
|
||||
write8(PCA9685_MODE1, oldmode | 0xa1); // This sets the MODE1 register to turn on auto increment.
|
||||
// This is why the beginTransmission below was not working.
|
||||
// Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX);
|
||||
}
|
||||
|
||||
void Adafruit_MS_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) {
|
||||
//Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off);
|
||||
|
||||
WIRE.beginTransmission(_i2caddr);
|
||||
#if ARDUINO >= 100
|
||||
WIRE.write(LED0_ON_L+4*num);
|
||||
WIRE.write(on);
|
||||
WIRE.write(on>>8);
|
||||
WIRE.write(off);
|
||||
WIRE.write(off>>8);
|
||||
#else
|
||||
WIRE.send(LED0_ON_L+4*num);
|
||||
WIRE.send((uint8_t)on);
|
||||
WIRE.send((uint8_t)(on>>8));
|
||||
WIRE.send((uint8_t)off);
|
||||
WIRE.send((uint8_t)(off>>8));
|
||||
#endif
|
||||
WIRE.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t Adafruit_MS_PWMServoDriver::read8(uint8_t addr) {
|
||||
WIRE.beginTransmission(_i2caddr);
|
||||
#if ARDUINO >= 100
|
||||
WIRE.write(addr);
|
||||
#else
|
||||
WIRE.send(addr);
|
||||
#endif
|
||||
WIRE.endTransmission();
|
||||
|
||||
WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)1);
|
||||
#if ARDUINO >= 100
|
||||
return WIRE.read();
|
||||
#else
|
||||
return WIRE.receive();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Adafruit_MS_PWMServoDriver::write8(uint8_t addr, uint8_t d) {
|
||||
WIRE.beginTransmission(_i2caddr);
|
||||
#if ARDUINO >= 100
|
||||
WIRE.write(addr);
|
||||
WIRE.write(d);
|
||||
#else
|
||||
WIRE.send(addr);
|
||||
WIRE.send(d);
|
||||
#endif
|
||||
WIRE.endTransmission();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user