mirror of
https://github.com/anklimov/lighthub
synced 2026-09-13 13:44:04 +00:00
@@ -1,2 +1,3 @@
|
||||
-DWiz5500
|
||||
-DARTNET_ENABLE
|
||||
-DDMX_SMOOTH
|
||||
|
||||
@@ -6,3 +6,4 @@
|
||||
-DSPILED_DISABLE
|
||||
-DAC_DISABLE
|
||||
#-DM5STACK
|
||||
-DOTA
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
-DMODBUS_DISABLE
|
||||
#-DCOUNTER_DISABLE
|
||||
-DOTA
|
||||
-std=gnu++11
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
-DWiz5500
|
||||
-DW5500_CS_PIN=53
|
||||
-DARTNET_ENABLE
|
||||
-DDMX_SMOOTH
|
||||
-DMODBUS_DIMMER_PARAM=SERIAL_8N1
|
||||
-DMODBUS_SERIAL_BAUD=9600
|
||||
|
||||
@@ -1 +1 @@
|
||||
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem1411 -b 19200 -p m16u2 -vvv -U flash:w:16u2.hex:i
|
||||
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem14101 -b 19200 -p m16u2 -vvv -U flash:w:16u2.hex:i
|
||||
|
||||
+5907
-5452
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,3 @@
|
||||
export PORT=cu.usbmodem1411
|
||||
export PORT=cu.usbmodem14201
|
||||
echo . | stty -f /dev/$PORT speed 1200
|
||||
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -e -w -v -b firmware.bin -R
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4923
-4593
File diff suppressed because it is too large
Load Diff
+4698
-4205
File diff suppressed because it is too large
Load Diff
+6100
-5637
File diff suppressed because it is too large
Load Diff
+4528
-4151
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -7,6 +7,7 @@
|
||||
|
||||
extern lan_status lanStatus;
|
||||
extern PubSubClient mqttClient;
|
||||
extern int8_t ethernetIdleCount;
|
||||
|
||||
int abstractCh::publishTopic(const char* topic, long value, const char* subtopic)
|
||||
{
|
||||
@@ -31,11 +32,11 @@ int abstractCh::publishTopic(const char* topic, const char * value, const char*
|
||||
strncpy(addrstr,topic,sizeof(addrstr));
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,topic);
|
||||
strncat(addrstr,subtopic,sizeof(addrstr));
|
||||
if (mqttClient.connected() && lanStatus == OPERATION)
|
||||
if (mqttClient.connected() && lanStatus == OPERATION && !ethernetIdleCount)
|
||||
{
|
||||
mqttClient.publish(addrstr, value, true);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ class abstractCh {
|
||||
public:
|
||||
abstractCh(){};
|
||||
virtual ~abstractCh(){};
|
||||
virtual int Poll() = 0;
|
||||
virtual int Poll(short cause) = 0;
|
||||
virtual int Setup() =0; //Should initialize hardware and reserve resources
|
||||
virtual int Anounce () {return 0;};
|
||||
virtual int Stop() {return 0;}; //Should free resources
|
||||
|
||||
@@ -26,11 +26,10 @@ int abstractIn::publish(float value, const char* subtopic)
|
||||
|
||||
int abstractIn::publish(char * value, const char* subtopic)
|
||||
{
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
if (in)
|
||||
{
|
||||
aJsonObject *emit = aJson.getObjectItem(in->inputObj, "emit");
|
||||
if (emit)
|
||||
if (emit && emit->type == aJson_String)
|
||||
{
|
||||
return publishTopic(emit->valuestring,value,subtopic);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ public:
|
||||
virtual int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true, int suffixCode=0, char* subItem=NULL) =0;
|
||||
virtual int isActive(){return 0;};
|
||||
virtual int getDefaultOnVal(){return 100;};
|
||||
virtual int getChanType(){return 0;}
|
||||
protected:
|
||||
Item * item;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "bright.h"
|
||||
|
||||
uint8_t getBright(uint8_t percent)
|
||||
{
|
||||
int index = map(percent,0,100,0,255);
|
||||
if (index>255) index=255;
|
||||
return getBright255(index);
|
||||
}
|
||||
|
||||
uint8_t getBright255(uint8_t percent)
|
||||
{
|
||||
#ifdef BRIGHT_LINEAR
|
||||
return percent;
|
||||
#else
|
||||
int val = stepvar[index];
|
||||
if (val>255) val=255;
|
||||
Serial.print(F("Bright:"));
|
||||
Serial.print(percent);
|
||||
Serial.print(F("->"));
|
||||
Serial.println(val);
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#define BRIGHT_LINEAR
|
||||
|
||||
|
||||
#ifdef BRIGHT_LOG
|
||||
const uint8_t stepvar[] PROGMEM =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
|
||||
0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A,
|
||||
0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C,
|
||||
0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D,
|
||||
0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F,
|
||||
0x0F, 0x10, 0x10, 0x10, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x13, 0x13, 0x14,
|
||||
0x14, 0x14, 0x15, 0x15, 0x16, 0x16,
|
||||
0x17, 0x17, 0x18, 0x18, 0x19, 0x19,
|
||||
0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D,
|
||||
0x1E, 0x1E, 0x1F, 0x20, 0x20, 0x21,
|
||||
0x22, 0x23, 0x23, 0x24, 0x25, 0x26,
|
||||
0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
|
||||
0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31,
|
||||
0x32, 0x33, 0x34, 0x35, 0x37, 0x38,
|
||||
0x39, 0x3A, 0x3B, 0x3D, 0x3E, 0x3F,
|
||||
0x41, 0x42, 0x44, 0x45, 0x47, 0x48,
|
||||
0x4A, 0x4C, 0x4D, 0x4F, 0x51, 0x52,
|
||||
0x54, 0x56, 0x58, 0x5A, 0x5C, 0x5E,
|
||||
0x60, 0x62, 0x64, 0x66, 0x69, 0x6B,
|
||||
0x6D, 0x70, 0x72, 0x75, 0x77, 0x7A,
|
||||
0x7C, 0x7F, 0x82, 0x85, 0x88, 0x8B,
|
||||
0x8E, 0x91, 0x94, 0x97, 0x9B, 0x9E,
|
||||
0xA2, 0xA5, 0xA9, 0xAC, 0xB0, 0xB4,
|
||||
0xB8, 0xBC, 0xC0, 0xC4, 0xC9, 0xCD,
|
||||
0xD2, 0xD6, 0xDB, 0xE0, 0xE5, 0xEA,
|
||||
0xEF, 0xF4, 0xF9, 0xFF};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BRIGHT_STEP
|
||||
const uint8_t stepvar[] PROGMEM =
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
|
||||
0x06, 0x06, 0x06, 0x06, 0x07, 0x07,
|
||||
0x07, 0x07, 0x08, 0x08, 0x08, 0x08,
|
||||
0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A,
|
||||
0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D,
|
||||
0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F,
|
||||
0x10, 0x10, 0x11, 0x11, 0x12, 0x12,
|
||||
0x13, 0x13, 0x14, 0x14, 0x15, 0x16,
|
||||
0x16, 0x17, 0x17, 0x18, 0x19, 0x19,
|
||||
0x1A, 0x1B, 0x1B, 0x1C, 0x1D, 0x1D,
|
||||
0x1E, 0x1F, 0x20, 0x20, 0x21, 0x22,
|
||||
0x23, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x29, 0x2A, 0x2B, 0x2C,
|
||||
0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
|
||||
0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x42, 0x43, 0x44, 0x45, 0x47,
|
||||
0x48, 0x49, 0x4B, 0x4C, 0x4D, 0x4F,
|
||||
0x50, 0x51, 0x53, 0x54, 0x56, 0x57,
|
||||
0x59, 0x5A, 0x5C, 0x5D, 0x5F, 0x60,
|
||||
0x62, 0x64, 0x65, 0x67, 0x68, 0x6A,
|
||||
0x6C, 0x6E, 0x6F, 0x71, 0x73, 0x75,
|
||||
0x76, 0x78, 0x7A, 0x7C, 0x7E, 0x80,
|
||||
0x82, 0x84, 0x85, 0x87, 0x89, 0x8B,
|
||||
0x8E, 0x90, 0x92, 0x94, 0x96, 0x98,
|
||||
0x9A, 0x9C, 0x9E, 0xA1, 0xA3, 0xA5,
|
||||
0xA7, 0xAA, 0xAC, 0xAE, 0xB1, 0xB3,
|
||||
0xB6, 0xB8, 0xBA, 0xBD, 0xBF, 0xC2,
|
||||
0xC4, 0xC7, 0xCA, 0xCC, 0xCF, 0xD1,
|
||||
0xD4, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
|
||||
0xE5, 0xE7, 0xEA, 0xED, 0xF0, 0xF3,
|
||||
0xF6, 0xF9, 0xFC, 0xFF};
|
||||
#endif
|
||||
|
||||
uint8_t getBright(uint8_t percent);
|
||||
uint8_t getBright255(uint8_t percent);
|
||||
+61
-8
@@ -21,6 +21,7 @@ e-mail anklimov@gmail.com
|
||||
//#include <DmxSimple.h>
|
||||
//#include <DMXSerial.h>
|
||||
#include "options.h"
|
||||
#include "item.h"
|
||||
|
||||
#ifdef _dmxin
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
@@ -35,6 +36,13 @@ DMXESPSerial dmxout;
|
||||
#endif
|
||||
|
||||
uint8_t * DMXin = NULL;
|
||||
|
||||
#ifdef DMX_SMOOTH
|
||||
uint8_t * DMXinterimBuf = NULL;
|
||||
uint16_t DMXOUT_Channels=0;
|
||||
uint32_t checkTimestamp=0L;
|
||||
#endif
|
||||
|
||||
int D_State=0;
|
||||
|
||||
unsigned long D_checkT=0;
|
||||
@@ -61,16 +69,16 @@ int itemCtrl2(char* name,int r,int g, int b, int w)
|
||||
short itemaddr = aJson.getArrayItem(itemArr,1)->valueint;
|
||||
switch (itemtype){
|
||||
#ifdef _dmxout
|
||||
case 0: //Dimmed light
|
||||
case CH_DIMMER: //Dimmed light
|
||||
|
||||
DmxWrite(itemaddr, w);
|
||||
break;
|
||||
|
||||
|
||||
case 1: //Colour RGBW
|
||||
case CH_RGBW: //Colour RGBW
|
||||
DmxWrite(itemaddr+3, w);
|
||||
|
||||
case 2: // RGB
|
||||
case CH_RGB: // RGB
|
||||
{
|
||||
|
||||
DmxWrite(itemaddr, r);
|
||||
@@ -79,13 +87,13 @@ int itemCtrl2(char* name,int r,int g, int b, int w)
|
||||
|
||||
break; }
|
||||
#endif
|
||||
case 7: //Group
|
||||
case CH_GROUP: //Group
|
||||
aJsonObject *groupArr= aJson.getArrayItem(itemArr, 1);
|
||||
if (groupArr && (groupArr->type==aJson_Array))
|
||||
{ aJsonObject *i =groupArr->child;
|
||||
while (i)
|
||||
{ //Serial.println(i->valuestring);
|
||||
itemCtrl2(i->valuestring,r,g,b,w);
|
||||
if (i->type == aJson_String) itemCtrl2(i->valuestring,r,g,b,w);
|
||||
i=i->next;}
|
||||
}
|
||||
} //itemtype
|
||||
@@ -100,7 +108,9 @@ void DMXImmediateUpdate(short tch,short r, short g, short b, short w) {
|
||||
if (dmxArr && (dmxArr->type==aJson_Array))
|
||||
|
||||
{
|
||||
char* itemname = aJson.getArrayItem(dmxArr,tch)->valuestring;
|
||||
aJsonObject *DMXch = aJson.getArrayItem(dmxArr,tch);
|
||||
char* itemname = NULL;
|
||||
if (DMXch->type == aJson_String) itemname=DMXch->valuestring;
|
||||
if (itemname) itemCtrl2(itemname,r,g,b,w);
|
||||
}
|
||||
}
|
||||
@@ -112,7 +122,6 @@ void DMXSemiImmediateUpdate(short tch,short trh, int val)
|
||||
|
||||
void DMXput(void)
|
||||
{
|
||||
int t;
|
||||
for (short tch=0; tch<=3 ; tch++)
|
||||
{
|
||||
short base = tch*4;
|
||||
@@ -160,6 +169,7 @@ for (short tch=0; tch<=3 ; tch++)
|
||||
{
|
||||
// CHSV hsv;
|
||||
// CRGB rgb;
|
||||
DMXOUT_propagate();
|
||||
#if defined(_dmxin)
|
||||
|
||||
short t,tch;
|
||||
@@ -191,7 +201,7 @@ for (int i=1; i<17; i++) {Serial.print(dmxin.read(i));Serial.print(";");}
|
||||
void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP)
|
||||
{
|
||||
#ifdef _dmxout
|
||||
for (int i = 0 ; i < length && i<MAX_CHANNELS ; i++)
|
||||
for (unsigned int i = 0 ; i < length && i<MAX_CHANNELS ; i++)
|
||||
{
|
||||
DmxWrite(i+1,data[i]);
|
||||
}
|
||||
@@ -249,8 +259,42 @@ dmxout.setTxMaxChannels(channels);
|
||||
#ifndef DMX_DISABLE
|
||||
for (int i=1;i<=channels;i++) DmxWrite(i,0);
|
||||
#endif
|
||||
|
||||
#ifdef DMX_SMOOTH
|
||||
if (DMXinterimBuf) delete DMXinterimBuf;
|
||||
DMXinterimBuf = new uint8_t [channels];
|
||||
DMXOUT_Channels=channels;
|
||||
for (int i=1;i<=channels;i++) DMXinterimBuf[i]=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DMXOUT_propagate()
|
||||
{
|
||||
#ifdef DMX_SMOOTH
|
||||
uint32_t now = millis();
|
||||
if (now<checkTimestamp) return;
|
||||
|
||||
for(int i=1;i<=DMXOUT_Channels;i++)
|
||||
{
|
||||
uint8_t currLevel=dmxout.getTx(i);
|
||||
uint16_t delta = currLevel-DMXinterimBuf[i-1];
|
||||
if (delta)
|
||||
{
|
||||
uint16_t step = abs(delta) >> 4;
|
||||
if (!step) step=1;
|
||||
|
||||
if (delta<0)
|
||||
DmxWrite2(i,currLevel+step);
|
||||
|
||||
if (delta>0)
|
||||
DmxWrite2(i,currLevel-step);
|
||||
}
|
||||
}
|
||||
checkTimestamp=now+DMX_SMOOTH_DELAY;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ArtnetSetup()
|
||||
{
|
||||
#ifdef _artnet
|
||||
@@ -259,3 +303,12 @@ void ArtnetSetup()
|
||||
if (artnet) artnet->setArtDmxCallback(onDmxFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void DmxWriteBuf(uint16_t chan,uint8_t val)
|
||||
{
|
||||
#ifdef DMX_SMOOTH
|
||||
if (chan && chan<=DMXOUT_Channels)
|
||||
DMXinterimBuf[chan-1] = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -32,6 +32,35 @@ e-mail anklimov@gmail.com
|
||||
|
||||
#if defined(_dmxout)
|
||||
|
||||
#if defined DMX_SMOOTH
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#include <DmxSimple.h>
|
||||
#define DmxWrite DmxSimple.write
|
||||
//#define DmxWrite DmxWriteBuf
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESPDMX.h>
|
||||
extern DMXESPSerial dmxout;
|
||||
#define DmxWrite dmxout.write
|
||||
//#define DmxWrite DmxWriteBuf
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#include <ESPDMX.h>
|
||||
extern DMXESPSerial dmxout;
|
||||
#define DmxWrite dmxout.write
|
||||
//#define DmxWrite DmxWriteBuf
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
#include <DmxDue.h>
|
||||
#define DmxWrite2 dmxout.write
|
||||
#define DmxWrite DmxWriteBuf
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#include <DmxSimple.h>
|
||||
#define DmxWrite DmxSimple.write
|
||||
@@ -52,6 +81,8 @@ extern DMXESPSerial dmxout;
|
||||
#if defined(__SAM3X8E__)
|
||||
#include <DmxDue.h>
|
||||
#define DmxWrite dmxout.write
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -78,3 +109,5 @@ void ArtnetSetup();
|
||||
void DMXCheck(void);
|
||||
int itemCtrl2(char* name,int r,int g, int b, int w);
|
||||
void ArtnetSetup();
|
||||
void DmxWriteBuf(uint16_t chan,uint8_t val);
|
||||
void DMXOUT_propagate();
|
||||
|
||||
+446
-52
@@ -34,6 +34,7 @@ e-mail anklimov@gmail.com
|
||||
extern PubSubClient mqttClient;
|
||||
extern aJsonObject *root;
|
||||
extern int8_t ethernetIdleCount;
|
||||
extern int8_t configLocked;
|
||||
|
||||
#if !defined(DHT_DISABLE) || !defined(COUNTER_DISABLE)
|
||||
static volatile unsigned long nextPollMillisValue[5];
|
||||
@@ -113,7 +114,7 @@ void Input::Parse()
|
||||
void Input::setup()
|
||||
{
|
||||
if (!isValid() || (!root)) return;
|
||||
|
||||
/*
|
||||
#ifndef CSSHDC_DISABLE
|
||||
if (inType == IN_CCS811)
|
||||
{
|
||||
@@ -127,10 +128,55 @@ if (!isValid() || (!root)) return;
|
||||
}
|
||||
// TODO rest types setup
|
||||
#endif
|
||||
*/
|
||||
store->aslong=0;
|
||||
uint8_t inputPinMode = INPUT; //if IN_ACTIVE_HIGH
|
||||
switch (inType)
|
||||
{
|
||||
case IN_PUSH_ON:
|
||||
case IN_PUSH_TOGGLE :
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
||||
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
||||
pinMode(pin, inputPinMode);
|
||||
|
||||
store->state=IS_IDLE;
|
||||
break;
|
||||
|
||||
case IN_ANALOG:
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
case IN_ANALOG | IN_ACTIVE_HIGH:
|
||||
pinMode(pin, inputPinMode);
|
||||
break;
|
||||
|
||||
case IN_DHT22:
|
||||
case IN_COUNTER:
|
||||
case IN_UPTIME:
|
||||
break;
|
||||
|
||||
#ifndef CSSHDC_DISABLE
|
||||
case IN_CCS811:
|
||||
{
|
||||
in_ccs811 ccs811(this);
|
||||
ccs811.Setup();
|
||||
}
|
||||
break;
|
||||
|
||||
case IN_HDC1080:
|
||||
{
|
||||
in_hdc1080 hdc1080(this);
|
||||
hdc1080.Setup();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
} //switch
|
||||
|
||||
}
|
||||
|
||||
int Input::poll(short cause) {
|
||||
int Input::Poll(short cause) {
|
||||
|
||||
if (!isValid()) return -1;
|
||||
#ifndef CSSHDC_DISABLE
|
||||
@@ -140,17 +186,18 @@ if (!isValid()) return -1;
|
||||
|
||||
switch (cause) {
|
||||
case CHECK_INPUT: //Fast polling
|
||||
case CHECK_INTERRUPT: //Realtime polling
|
||||
switch (inType)
|
||||
{
|
||||
case IN_PUSH_ON:
|
||||
case IN_PUSH_ON | IN_ACTIVE_HIGH:
|
||||
case IN_PUSH_TOGGLE :
|
||||
case IN_PUSH_TOGGLE | IN_ACTIVE_HIGH:
|
||||
contactPoll();
|
||||
contactPoll(cause);
|
||||
break;
|
||||
case IN_ANALOG:
|
||||
case IN_ANALOG | IN_ACTIVE_HIGH:
|
||||
analogPoll();
|
||||
analogPoll(cause);
|
||||
break;
|
||||
|
||||
// No fast polling
|
||||
@@ -167,10 +214,10 @@ switch (cause) {
|
||||
{
|
||||
#ifndef CSSHDC_DISABLE
|
||||
case IN_CCS811:
|
||||
_ccs811.Poll();
|
||||
_ccs811.Poll(POLLING_SLOW);
|
||||
break;
|
||||
case IN_HDC1080:
|
||||
_hdc1080.Poll();
|
||||
_hdc1080.Poll(POLLING_SLOW);
|
||||
break;
|
||||
#endif
|
||||
#ifndef DHT_DISABLE
|
||||
@@ -222,7 +269,7 @@ void Input::counterPoll() {
|
||||
debugSerial<<F("IN:")<<(pin)<<F(" Counter type. val=")<<counterValue;
|
||||
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
if (emit) {
|
||||
if (emit && emit->type == aJson_String) {
|
||||
char valstr[10];
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
||||
@@ -281,7 +328,7 @@ void Input::uptimePoll() {
|
||||
if (nextPollTime() > millis())
|
||||
return;
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
if (emit) {
|
||||
if (emit && emit->type == aJson_String) {
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if(getIdxField()){
|
||||
publishDataToDomoticz(DHT_POLL_DELAY_DEFAULT, emit, "{\"idx\":%s,\"svalue\":\"%d\"}", getIdxField(), millis());
|
||||
@@ -376,9 +423,9 @@ void Input::dht22Poll() {
|
||||
#endif
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
aJsonObject *item = aJson.getObjectItem(inputObj, "item");
|
||||
if (item) thermoSetCurTemp(item->valuestring, temp);
|
||||
if (item && item->type == aJson_String) thermoSetCurTemp(item->valuestring, temp);
|
||||
debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") << humidity << F("%")<<endl;
|
||||
if (emit && temp && humidity && temp == temp && humidity == humidity) {
|
||||
if (emit && emit->type == aJson_String && temp && humidity && temp == temp && humidity == humidity) {
|
||||
char addrstr[MQTT_TOPIC_LENGTH] = "";
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if(getIdxField()){
|
||||
@@ -406,43 +453,375 @@ void Input::dht22Poll() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void Input::contactPoll() {
|
||||
boolean currentInputState;
|
||||
bool Input::executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
|
||||
{
|
||||
if (!cmd) return false;
|
||||
|
||||
switch (cmd->type)
|
||||
{
|
||||
case aJson_String: //legacy - no action
|
||||
break;
|
||||
case aJson_Array: //array - recursive iterate
|
||||
{
|
||||
configLocked++;
|
||||
aJsonObject * command = cmd->child;
|
||||
while (command)
|
||||
{
|
||||
executeCommand(command,toggle,defCmd);
|
||||
command = command->next;
|
||||
}
|
||||
configLocked--;
|
||||
}
|
||||
break;
|
||||
case aJson_Object:
|
||||
{
|
||||
aJsonObject *item = aJson.getObjectItem(cmd, "item");
|
||||
aJsonObject *icmd = aJson.getObjectItem(cmd, "icmd");
|
||||
aJsonObject *irev = aJson.getObjectItem(cmd, "irev");
|
||||
aJsonObject *ecmd = aJson.getObjectItem(cmd, "ecmd");
|
||||
aJsonObject *erev = aJson.getObjectItem(cmd, "erev");
|
||||
aJsonObject *emit = aJson.getObjectItem(cmd, "emit");
|
||||
|
||||
char * itemCommand;
|
||||
if (irev && toggle && irev->type == aJson_String) itemCommand = irev->valuestring;
|
||||
else if(icmd && icmd->type == aJson_String) itemCommand = icmd->valuestring;
|
||||
else itemCommand = defCmd;
|
||||
|
||||
char * emitCommand;
|
||||
if (erev && toggle && erev->type == aJson_String) emitCommand = erev->valuestring;
|
||||
else if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring;
|
||||
else emitCommand = defCmd;
|
||||
|
||||
debugSerial << F("IN:") << (pin) << F(" : ") <<endl;
|
||||
if (item) debugSerial << item->valuestring<< F(" -> ")<<itemCommand<<endl;
|
||||
if (emit) debugSerial << emit->valuestring<< F(" -> ")<<emitCommand<<endl;
|
||||
|
||||
|
||||
|
||||
|
||||
if (emit && emitCommand && emit->type == aJson_String) {
|
||||
/*
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
WiringPinMode inputPinMode;
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)||defined(ARDUINO_ARCH_AVR)||defined(ARDUINO_ARCH_ESP8266)||defined(ARDUINO_ARCH_ESP32)
|
||||
|
||||
TODO implement
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if (getIdxField())
|
||||
{ (newValue) ? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}",
|
||||
: publishDataToDomoticz(0,emit,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",getIdxField()); getIdxField())
|
||||
: publishDataToDomoticz(0, emit,
|
||||
"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",
|
||||
getIdxField());
|
||||
} else
|
||||
#endif
|
||||
*/
|
||||
uint32_t inputPinMode;
|
||||
uint8_t inputOnLevel;
|
||||
if (inType & IN_ACTIVE_HIGH) {
|
||||
inputOnLevel = HIGH;
|
||||
inputPinMode = INPUT;
|
||||
} else {
|
||||
inputOnLevel = LOW;
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
|
||||
{
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
||||
if (mqttClient.connected() && !ethernetIdleCount)
|
||||
{
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||
mqttClient.publish(addrstr, emitCommand , true);
|
||||
}
|
||||
}
|
||||
} // emit
|
||||
if (item && itemCommand && item->type == aJson_String) {
|
||||
//debugSerial <<F("Controlled item:")<< item->valuestring <<endl;
|
||||
Item it(item->valuestring);
|
||||
if (it.isValid()) it.Ctrl(itemCommand, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
} //switch type
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
||||
bool Input::changeState(uint8_t newState, short cause)
|
||||
{
|
||||
if (!inputObj || !store) return false;
|
||||
|
||||
if (newState == IS_REQSTATE)
|
||||
if (store->delayedState && cause != CHECK_INTERRUPT)
|
||||
{
|
||||
// Requested delayed change State and safe moment
|
||||
newState=store->reqState; //Retrieve requested state
|
||||
debugSerial<<F("Pended state retrieved:")<<newState;
|
||||
|
||||
}
|
||||
pinMode(pin, inputPinMode);
|
||||
else return true; // No pended State
|
||||
else if (store->delayedState)
|
||||
return false; //State changing is postponed already (( giving up
|
||||
|
||||
aJsonObject *cmd = NULL;
|
||||
int8_t toggle=0;
|
||||
if (newState!=store->state) debugSerial<<F("#")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
|
||||
switch (newState)
|
||||
{
|
||||
case IS_IDLE:
|
||||
switch (store->state)
|
||||
{
|
||||
case IS_RELEASED: //click
|
||||
cmd = aJson.getObjectItem(inputObj, "click");
|
||||
toggle=store->toggle1;
|
||||
break;
|
||||
case IS_RELEASED2: //doubleclick
|
||||
cmd = aJson.getObjectItem(inputObj, "dclick");
|
||||
toggle=store->toggle2;
|
||||
break;
|
||||
case IS_PRESSED3: //tripple click
|
||||
cmd = aJson.getObjectItem(inputObj, "tclick");
|
||||
toggle=store->toggle3;
|
||||
break;
|
||||
case IS_WAITPRESS: //do nothing
|
||||
break;
|
||||
default: //rcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
;
|
||||
}
|
||||
break;
|
||||
case IS_PRESSED: //scmd
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd");
|
||||
toggle=store->toggle1;
|
||||
store->toggle1 = !store->toggle1;
|
||||
break;
|
||||
case IS_PRESSED2: //scmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd2");
|
||||
toggle=store->toggle2;
|
||||
store->toggle2 = !store->toggle2;
|
||||
break;
|
||||
case IS_PRESSED3: //scmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "scmd3");
|
||||
toggle=store->toggle3;
|
||||
store->toggle3 = !store->toggle3;
|
||||
break;
|
||||
|
||||
case IS_RELEASED: //rcmd
|
||||
case IS_WAITPRESS:
|
||||
case IS_RELEASED2:
|
||||
cmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
// toggle=state->toggle1;
|
||||
|
||||
break;
|
||||
case IS_LONG: //lcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd");
|
||||
toggle=store->toggle1;
|
||||
break;
|
||||
case IS_REPEAT: //rpcmd
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd");
|
||||
toggle=store->toggle1;
|
||||
break;
|
||||
case IS_LONG2: //lcmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd2");
|
||||
toggle=store->toggle2;
|
||||
break;
|
||||
case IS_REPEAT2: //rpcmd2
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd2");
|
||||
toggle=store->toggle2;
|
||||
break;
|
||||
case IS_LONG3: //lcmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "lcmd3");
|
||||
toggle=store->toggle3;
|
||||
break;
|
||||
case IS_REPEAT3: //rpcmd3
|
||||
cmd = aJson.getObjectItem(inputObj, "rpcmd3");
|
||||
toggle=store->toggle3;
|
||||
break;
|
||||
|
||||
}
|
||||
if (!cmd)
|
||||
{
|
||||
store->state=newState;
|
||||
return true; //nothing to do
|
||||
}
|
||||
if (cause != CHECK_INTERRUPT)
|
||||
{
|
||||
store->state=newState;
|
||||
executeCommand(cmd,toggle);
|
||||
//Executed
|
||||
store->delayedState=false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Postpone actual execution
|
||||
store->reqState=store->state;
|
||||
store->delayedState=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Input::contactPoll(short cause) {
|
||||
boolean currentInputState;
|
||||
if (!store) return;
|
||||
|
||||
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
|
||||
|
||||
|
||||
uint8_t inputOnLevel;
|
||||
if (inType & IN_ACTIVE_HIGH) inputOnLevel = HIGH;
|
||||
else inputOnLevel = LOW;
|
||||
|
||||
|
||||
currentInputState = (digitalRead(pin) == inputOnLevel);
|
||||
if (currentInputState != store->currentValue) // value changed
|
||||
|
||||
switch (store->state) //Timer based transitions
|
||||
{
|
||||
case IS_PRESSED:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||
{
|
||||
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(inputObj, "rpcmd")) changeState(IS_WAITRELEASE, cause);
|
||||
else changeState(IS_LONG, cause);
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_PRESSED2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||
{
|
||||
if (!aJson.getObjectItem(inputObj, "lcmd2") && !aJson.getObjectItem(inputObj, "rpcmd2")) changeState(IS_WAITRELEASE, cause);
|
||||
else changeState(IS_LONG2, cause);
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_LONG2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT2, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT2:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT2, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_PRESSED3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||
{
|
||||
if (!aJson.getObjectItem(inputObj, "lcmd3") && !aJson.getObjectItem(inputObj, "rpcmd3")) //No longpress handlers
|
||||
{
|
||||
if (aJson.getObjectItem(inputObj, "scmd3")) changeState(IS_WAITRELEASE, cause); //was used
|
||||
else changeState(IS_PRESSED2, cause); // completely empty trippleClick section - fallback to first click handler
|
||||
}
|
||||
else changeState(IS_LONG3, cause);
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_LONG3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT3, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_REPEAT3:
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||
{
|
||||
changeState(IS_REPEAT3, cause);
|
||||
store->timestamp16 = millis() & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_RELEASED:
|
||||
case IS_RELEASED2:
|
||||
case IS_WAITPRESS:
|
||||
|
||||
|
||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause);
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentInputState != store->lastValue) // value changed
|
||||
{
|
||||
if (store->bounce) store->bounce = store->bounce - 1;
|
||||
else //confirmed change
|
||||
{
|
||||
if (inType & IN_PUSH_TOGGLE) {
|
||||
store->timestamp16 = millis() & 0xFFFF; //Saving timestamp of changing
|
||||
|
||||
if (inType & IN_PUSH_TOGGLE) { //To refactore
|
||||
if (currentInputState) { //react on leading edge only (change from 0 to 1)
|
||||
store->logicState = !store->logicState;
|
||||
store->currentValue = currentInputState;
|
||||
onContactChanged(store->logicState);
|
||||
//store->logicState = !store->logicState;
|
||||
store->lastValue = currentInputState;
|
||||
onContactChanged(store->toggle1);
|
||||
}
|
||||
} else
|
||||
|
||||
{
|
||||
onContactChanged(currentInputState); //Legacy input - to remove later
|
||||
|
||||
bool res = true;
|
||||
if (currentInputState) //Button pressed state transitions
|
||||
|
||||
switch (store->state)
|
||||
{
|
||||
case IS_IDLE:
|
||||
res = changeState(IS_PRESSED, cause);
|
||||
|
||||
break;
|
||||
|
||||
case IS_RELEASED:
|
||||
case IS_WAITPRESS:
|
||||
res = changeState(IS_PRESSED2, cause);
|
||||
|
||||
break;
|
||||
|
||||
case IS_RELEASED2:
|
||||
|
||||
res = changeState(IS_PRESSED3, cause);
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch (store->state) //Button released state transitions
|
||||
{
|
||||
case IS_PRESSED:
|
||||
|
||||
res = changeState(IS_RELEASED, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
case IS_REPEAT:
|
||||
case IS_WAITRELEASE:
|
||||
res = changeState(IS_WAITPRESS, cause);
|
||||
break;
|
||||
|
||||
case IS_PRESSED2:
|
||||
res = changeState(IS_RELEASED2, cause);
|
||||
break;
|
||||
|
||||
case IS_LONG2:
|
||||
case IS_REPEAT2:
|
||||
case IS_LONG3:
|
||||
case IS_REPEAT3:
|
||||
case IS_PRESSED3:
|
||||
res = changeState(IS_IDLE, cause);
|
||||
break;
|
||||
}
|
||||
if (res) { //State changed or postponed
|
||||
// store->logicState = currentInputState;
|
||||
store->lastValue = currentInputState;
|
||||
}
|
||||
} else {
|
||||
store->logicState = currentInputState;
|
||||
store->currentValue = currentInputState;
|
||||
onContactChanged(currentInputState);
|
||||
}
|
||||
// store->currentValue = currentInputState;
|
||||
}
|
||||
@@ -451,23 +830,26 @@ void Input::contactPoll() {
|
||||
}
|
||||
|
||||
|
||||
void Input::analogPoll() {
|
||||
|
||||
void Input::analogPoll(short cause) {
|
||||
int16_t inputVal;
|
||||
int32_t mappedInputVal; // 10x inputVal
|
||||
aJsonObject *inputMap = aJson.getObjectItem(inputObj, "map");
|
||||
int16_t Noize = ANALOG_NOIZE;
|
||||
short simple = 0;
|
||||
uint32_t inputPinMode;
|
||||
// uint32_t inputPinMode;
|
||||
int max=1024*10;
|
||||
int min=0;
|
||||
|
||||
|
||||
/*
|
||||
if (inType & IN_ACTIVE_HIGH) {
|
||||
inputPinMode = INPUT;
|
||||
} else {
|
||||
inputPinMode = INPUT_PULLUP;
|
||||
}
|
||||
|
||||
pinMode(pin, inputPinMode);
|
||||
*/
|
||||
inputVal = analogRead(pin);
|
||||
// Mapping
|
||||
if (inputMap && inputMap->type == aJson_Array)
|
||||
@@ -483,8 +865,15 @@ void Input::analogPoll() {
|
||||
|
||||
if (aJson.getArraySize(inputMap)==5) Noize = aJson.getArrayItem(inputMap, 4)->valueint;
|
||||
|
||||
if (mappedInputVal>max) mappedInputVal = max;
|
||||
if (mappedInputVal<min) mappedInputVal = min;
|
||||
if (mappedInputVal>max)
|
||||
{
|
||||
mappedInputVal = max;
|
||||
inputVal = 1023;
|
||||
}
|
||||
if (mappedInputVal<min) {
|
||||
mappedInputVal = min;
|
||||
inputVal = 0;
|
||||
}
|
||||
|
||||
if (aJson.getArraySize(inputMap)==2)
|
||||
{
|
||||
@@ -522,12 +911,14 @@ void Input::analogPoll() {
|
||||
|
||||
|
||||
void Input::onContactChanged(int newValue) {
|
||||
debugSerial << F("IN:") << (pin) << F("=") << newValue << endl;
|
||||
|
||||
aJsonObject *item = aJson.getObjectItem(inputObj, "item");
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
if (!item && !emit) return;
|
||||
aJsonObject *scmd = aJson.getObjectItem(inputObj, "scmd");
|
||||
aJsonObject *rcmd = aJson.getObjectItem(inputObj, "rcmd");
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
if (emit) {
|
||||
debugSerial << F("LEGACY IN:") << (pin) << F("=") << newValue << endl;
|
||||
if (emit && emit->type == aJson_String) {
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if (getIdxField())
|
||||
{ (newValue) ? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}",
|
||||
@@ -544,26 +935,26 @@ if (mqttClient.connected() && !ethernetIdleCount)
|
||||
{
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||
if (newValue) { //send set command
|
||||
if (!scmd) mqttClient.publish(addrstr, "ON", true);
|
||||
if (!scmd || scmd->type != aJson_String) mqttClient.publish(addrstr, "ON", true);
|
||||
else if (strlen(scmd->valuestring))
|
||||
mqttClient.publish(addrstr, scmd->valuestring, true);
|
||||
} else { //send reset command
|
||||
if (!rcmd) mqttClient.publish(addrstr, "OFF", true);
|
||||
if (!rcmd || rcmd->type == aJson_String) mqttClient.publish(addrstr, "OFF", true);
|
||||
else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // emit
|
||||
if (item) {
|
||||
if (item && item->type == aJson_String) {
|
||||
//debugSerial <<F("Controlled item:")<< item->valuestring <<endl;
|
||||
Item it(item->valuestring);
|
||||
if (it.isValid()) {
|
||||
if (newValue) { //send set command
|
||||
if (!scmd) it.Ctrl(CMD_ON, 0, NULL, true);
|
||||
if (!scmd || scmd->type != aJson_String) it.Ctrl(CMD_ON, 0, NULL, true);
|
||||
else if (strlen(scmd->valuestring))
|
||||
it.Ctrl(scmd->valuestring, true);
|
||||
} else { //send reset command
|
||||
if (!rcmd) it.Ctrl(CMD_OFF, 0, NULL, true);
|
||||
if (!rcmd || rcmd->type != aJson_String) it.Ctrl(CMD_OFF, 0, NULL, true);
|
||||
else if (strlen(rcmd->valuestring))
|
||||
it.Ctrl(rcmd->valuestring, true);
|
||||
}
|
||||
@@ -577,7 +968,7 @@ void Input::onAnalogChanged(float newValue) {
|
||||
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
|
||||
|
||||
|
||||
if (emit) {
|
||||
if (emit && emit->type == aJson_String) {
|
||||
|
||||
//#ifdef WITH_DOMOTICZ
|
||||
// if (getIdxField()) {
|
||||
@@ -595,7 +986,7 @@ void Input::onAnalogChanged(float newValue) {
|
||||
mqttClient.publish(addrstr, strVal, true);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
if (item && item->type == aJson_String) {
|
||||
int intNewValue = round(newValue);
|
||||
Item it(item->valuestring);
|
||||
if (it.isValid()) {
|
||||
@@ -608,6 +999,8 @@ void Input::onAnalogChanged(float newValue) {
|
||||
bool Input::publishDataToDomoticz(int pollTimeIncrement, aJsonObject *emit, const char *format, ...)
|
||||
{
|
||||
#ifdef WITH_DOMOTICZ
|
||||
if (emit && emit->type == aJson_String)
|
||||
{
|
||||
debugSerial << F("\nDomoticz valstr:");
|
||||
char valstr[50];
|
||||
va_list args;
|
||||
@@ -620,6 +1013,7 @@ bool Input::publishDataToDomoticz(int pollTimeIncrement, aJsonObject *emit, cons
|
||||
if (pollTimeIncrement)
|
||||
setNextPollTime(millis() + pollTimeIncrement);
|
||||
// debugSerial << F(" NextPollMillis=") << nextPollTime() << endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
@@ -627,7 +1021,7 @@ bool Input::publishDataToDomoticz(int pollTimeIncrement, aJsonObject *emit, cons
|
||||
|
||||
char* Input::getIdxField() {
|
||||
aJsonObject *idx = aJson.getObjectItem(inputObj, "idx");
|
||||
if(idx&&idx->valuestring)
|
||||
if(idx&& idx->type == aJson_String && idx->valuestring)
|
||||
return idx->valuestring;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+49
-7
@@ -35,13 +35,39 @@ e-mail anklimov@gmail.com
|
||||
#define IN_COUNTER 8
|
||||
#define IN_UPTIME 16
|
||||
|
||||
#define IS_IDLE 0
|
||||
#define IS_PRESSED 1
|
||||
#define IS_RELEASED 2
|
||||
#define IS_LONG 3
|
||||
#define IS_REPEAT 4
|
||||
#define IS_WAITPRESS 5
|
||||
#define IS_PRESSED2 6
|
||||
#define IS_RELEASED2 7
|
||||
#define IS_LONG2 8u
|
||||
#define IS_REPEAT2 9u
|
||||
#define IS_PRESSED3 10u
|
||||
#define IS_LONG3 11u
|
||||
#define IS_REPEAT3 12u
|
||||
#define IS_WAITRELEASE 13u
|
||||
#define IS_REQSTATE 0xFF
|
||||
|
||||
|
||||
|
||||
#define SAME_STATE_ATTEMPTS 3
|
||||
#define ANALOG_STATE_ATTEMPTS 6
|
||||
#define ANALOG_NOIZE 1
|
||||
|
||||
#define CHECK_INPUT 1
|
||||
#define CHECK_SENSOR 2
|
||||
#define CHECK_SENSOR 1
|
||||
#define CHECK_INPUT 2
|
||||
#define CHECK_INTERRUPT 3
|
||||
|
||||
|
||||
#define T_LONG 1000
|
||||
#define T_IDLE 600
|
||||
#define T_RPT 300
|
||||
#define T_RPT_PULSE 150
|
||||
|
||||
|
||||
|
||||
// in syntaxis
|
||||
// "pin": { "T":"N", "emit":"out_emit", item:"out_item", "scmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd": "ON,OFF,TOGGLE,INCREASE,DECREASE", "rcmd":"repeat_command" }
|
||||
@@ -79,11 +105,25 @@ extern aJsonObject *inputs;
|
||||
typedef union {
|
||||
long int aslong;
|
||||
uint32_t timestamp;
|
||||
// Analog input structure
|
||||
struct {
|
||||
int8_t logicState;
|
||||
int8_t bounce;
|
||||
uint8_t reserved;
|
||||
uint8_t logicState;
|
||||
int16_t currentValue;
|
||||
};
|
||||
// Digital input structure
|
||||
struct {
|
||||
uint8_t toggle1:1;
|
||||
uint8_t toggle2:1;
|
||||
uint8_t toggle3:1;
|
||||
uint8_t lastValue:1;
|
||||
uint8_t delayedState:1;
|
||||
uint8_t bounce:3;
|
||||
uint8_t state:4;
|
||||
uint8_t reqState:4;
|
||||
uint16_t timestamp16;
|
||||
|
||||
};
|
||||
|
||||
} inStore;
|
||||
|
||||
@@ -105,7 +145,7 @@ public:
|
||||
void onContactChanged(int newValue);
|
||||
void onAnalogChanged(float newValue);
|
||||
|
||||
int poll(short cause);
|
||||
int Poll(short cause);
|
||||
void setup();
|
||||
|
||||
static void inline onCounterChanged(int i);
|
||||
@@ -121,8 +161,8 @@ public:
|
||||
protected:
|
||||
void Parse();
|
||||
|
||||
void contactPoll();
|
||||
void analogPoll();
|
||||
void contactPoll(short cause);
|
||||
void analogPoll(short cause);
|
||||
|
||||
void dht22Poll();
|
||||
|
||||
@@ -140,4 +180,6 @@ protected:
|
||||
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
||||
|
||||
char* getIdxField();
|
||||
bool changeState(uint8_t newState, short cause);
|
||||
bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL);
|
||||
};
|
||||
|
||||
+463
-134
File diff suppressed because it is too large
Load Diff
+32
-21
@@ -1,4 +1,4 @@
|
||||
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
|
||||
/* Copyright © 2017-2020 Andrey Klimov. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,14 @@ GIT: https://github.com/anklimov/lighthub
|
||||
e-mail anklimov@gmail.com
|
||||
|
||||
*/
|
||||
#pragma once
|
||||
#include "options.h"
|
||||
#include "abstractout.h"
|
||||
|
||||
#define POLLING_SLOW 1
|
||||
#define POLLING_FAST 2
|
||||
#define POLLING_INT 3
|
||||
|
||||
#define S_NOTFOUND 0
|
||||
#define S_SETnCMD 0
|
||||
#define S_CMD 1
|
||||
@@ -28,16 +33,10 @@ e-mail anklimov@gmail.com
|
||||
#define S_RGB 4
|
||||
#define S_FAN 5
|
||||
#define S_MODE 6
|
||||
#define S_HUE 7
|
||||
#define S_SAT 8
|
||||
#define S_ADDITIONAL 64
|
||||
/*
|
||||
|
||||
#define S_RPM 11
|
||||
#define S_TEMP 3
|
||||
#define S_SETPOINT 5
|
||||
#define S_POWER 6
|
||||
#define S_VOL 7
|
||||
#define S_HEAT 8
|
||||
*/
|
||||
#define CH_DIMMER 0 //DMX 1 ch
|
||||
#define CH_RGBW 1 //DMX 4 ch
|
||||
#define CH_RGB 2 //DMX 3 ch
|
||||
@@ -50,6 +49,12 @@ e-mail anklimov@gmail.com
|
||||
#define CH_VC 9 //Vacom modbus motor regulator
|
||||
#define CH_AC 10 //AC Haier
|
||||
#define CH_SPILED 11
|
||||
#define CH_MOTOR 12
|
||||
//#define CHANNEL_TYPES 13
|
||||
|
||||
//static uint32_t pollInterval[CHANNEL_TYPES] = {0,0,0,0,MODB};
|
||||
//static uint32_t nextPollTime[CHANNEL_TYPES] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
#define CH_WHITE 127//
|
||||
|
||||
#define CMD_NUM 0
|
||||
@@ -72,20 +77,21 @@ e-mail anklimov@gmail.com
|
||||
#define CMD_AUTO 0xc
|
||||
#define CMD_FAN 0xd
|
||||
#define CMD_DRY 0xe
|
||||
#define CMD_SET 0xf
|
||||
#define CMD_HIGH 0x10
|
||||
//#define CMD_SET 0xf
|
||||
#define CMD_HIGH 0x10 //AC fan leve
|
||||
#define CMD_MED 0x11
|
||||
#define CMD_LOW 0x12
|
||||
//#define CMD_CURTEMP 0xf
|
||||
#define CMD_MASK 0xff
|
||||
#define FLAG_MASK 0x0f00
|
||||
#define FLAG_MASK 0xff00
|
||||
|
||||
|
||||
#define SEND_COMMAND 0x100
|
||||
#define SEND_PARAMETERS 0x200
|
||||
#define SEND_RETRY 0x400
|
||||
#define SEND_DEFFERED 0x800
|
||||
|
||||
#define ACTION_NEEDED 0x1000
|
||||
#define ACTION_IN_PROCESS 0x2000
|
||||
|
||||
//#define CMD_REPORT 32
|
||||
|
||||
@@ -147,7 +153,7 @@ typedef union
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
aJsonObject *itemArr, *itemArg,*itemVal;
|
||||
aJsonObject *itemArr, *itemArg,*itemVal,*itemExt;
|
||||
uint8_t itemType;
|
||||
abstractOut * driver;
|
||||
|
||||
@@ -164,33 +170,38 @@ class Item
|
||||
//int getVal(short n); //From VAL array. Negative if no array
|
||||
long int getVal(); //From int val OR array
|
||||
uint8_t getCmd();
|
||||
long int getExt(); //From int val OR array
|
||||
void setExt(long int par);
|
||||
void setCmd(uint8_t cmdValue);
|
||||
short getFlag (short flag=FLAG_MASK);
|
||||
void setFlag (short flag);
|
||||
void clearFlag (short flag);
|
||||
//void setVal(uint8_t n, int par);
|
||||
void setVal(long int par);
|
||||
//void copyPar (aJsonObject *itemV);
|
||||
int Poll(int cause);
|
||||
int SendStatus(int sendFlags);
|
||||
int isActive();
|
||||
int getChanType();
|
||||
inline int On (){return Ctrl(CMD_ON);};
|
||||
inline int Off(){return Ctrl(CMD_OFF);};
|
||||
inline int Toggle(){return Ctrl(CMD_TOGGLE);};
|
||||
int Poll();
|
||||
int SendStatus(int sendFlags);
|
||||
|
||||
protected:
|
||||
short cmd2changeActivity(int lastActivity, short defaultCmd = CMD_SET);
|
||||
//short cmd2changeActivity(int lastActivity, short defaultCmd = CMD_SET);
|
||||
int VacomSetFan (int8_t val, int8_t cmd=0);
|
||||
int VacomSetHeat(int addr, int8_t val, int8_t cmd=0);
|
||||
int VacomSetHeat(int8_t val, int8_t cmd=0);
|
||||
int modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint16_t value);
|
||||
int modbusDimmerSet(uint16_t value);
|
||||
void mb_fail();
|
||||
int isActive();
|
||||
void Parse();
|
||||
int checkModbusDimmer();
|
||||
int checkModbusDimmer(int data);
|
||||
boolean checkModbusRetry();
|
||||
boolean checkVCRetry();
|
||||
boolean checkHeatRetry();
|
||||
void sendDelayedStatus();
|
||||
|
||||
int checkFM();
|
||||
char defaultSubItem[10];
|
||||
int defaultSuffixCode;
|
||||
|
||||
};
|
||||
|
||||
+157
-30
@@ -67,6 +67,9 @@ PWM Out
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#if defined(OTA)
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
DueFlashStorage EEPROM;
|
||||
@@ -154,6 +157,7 @@ aJsonObject *pollingItem = NULL;
|
||||
bool owReady = false;
|
||||
bool configOk = false;
|
||||
int8_t ethernetIdleCount =0;
|
||||
int8_t configLocked = 0;
|
||||
|
||||
#ifdef _modbus
|
||||
ModbusMaster node;
|
||||
@@ -174,6 +178,24 @@ void watchdogSetup(void) {} //Do not remove - strong re-definition WDT Init f
|
||||
void cleanConf()
|
||||
{
|
||||
if (!root) return;
|
||||
debugSerial<<F("Unlocking config ...");
|
||||
while (configLocked)
|
||||
{
|
||||
//wdt_res();
|
||||
cmdPoll();
|
||||
#ifdef _owire
|
||||
if (owReady && owArr) owLoop();
|
||||
#endif
|
||||
#ifdef _dmxin
|
||||
DMXCheck();
|
||||
#endif
|
||||
if (lanStatus != RETAINING_COLLECTING) pollingLoop();
|
||||
thermoLoop();
|
||||
inputLoop();
|
||||
}
|
||||
|
||||
pollingItem = NULL;;
|
||||
|
||||
debugSerial<<F("Deleting conf. RAM was:")<<freeRam();
|
||||
aJson.deleteItem(root);
|
||||
root = NULL;
|
||||
@@ -301,6 +323,8 @@ lan_status lanLoop() {
|
||||
break;
|
||||
|
||||
case HAVE_IP_ADDRESS:
|
||||
|
||||
if (configLocked) return HAVE_IP_ADDRESS;
|
||||
if (!configOk)
|
||||
lanStatus = loadConfigFromHttp(0, NULL);
|
||||
else lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
|
||||
@@ -308,12 +332,15 @@ lan_status lanLoop() {
|
||||
|
||||
case IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER:
|
||||
wdt_res();
|
||||
|
||||
|
||||
|
||||
ip_ready_config_loaded_connecting_to_broker();
|
||||
break;
|
||||
|
||||
case RETAINING_COLLECTING:
|
||||
if (millis() > nextLanCheckTime) {
|
||||
char buf[MQTT_TOPIC_LENGTH];
|
||||
char buf[MQTT_TOPIC_LENGTH+1];
|
||||
|
||||
//Unsubscribe from status topics..
|
||||
//strncpy_P(buf, outprefix, sizeof(buf));
|
||||
@@ -441,7 +468,7 @@ void onMQTTConnect(){
|
||||
strncat_P(topic, homie_P, sizeof(topic));
|
||||
strncpy_P(buf, homiever_P, sizeof(buf));
|
||||
mqttClient.publish(topic,buf,true);
|
||||
|
||||
configLocked++;
|
||||
if (items) {
|
||||
char datatype[32]="\0";
|
||||
char format [64]="\0";
|
||||
@@ -503,9 +530,33 @@ void onMQTTConnect(){
|
||||
strncat_P(topic, nodes_P, sizeof(topic));
|
||||
/// mqttClient.publish(topic,buf,true);
|
||||
}
|
||||
configLocked--;
|
||||
#endif
|
||||
}
|
||||
|
||||
char* getStringFromConfig(aJsonObject * a, int i)
|
||||
{
|
||||
aJsonObject * element = NULL;
|
||||
if (!a) return NULL;
|
||||
if (a->type == aJson_Array)
|
||||
element = aJson.getArrayItem(a, i);
|
||||
// TODO - human readable JSON objects as alias
|
||||
|
||||
if (element && element->type == aJson_String) return element->valuestring;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* getStringFromConfig(aJsonObject * a, char * name)
|
||||
{
|
||||
aJsonObject * element = NULL;
|
||||
if (!a) return NULL;
|
||||
if (a->type == aJson_Object)
|
||||
element = aJson.getObjectItem(a, name);
|
||||
if (element && element->type == aJson_String) return element->valuestring;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void ip_ready_config_loaded_connecting_to_broker() {
|
||||
short n = 0;
|
||||
int port = 1883;
|
||||
@@ -517,14 +568,14 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
||||
char syslogDeviceHostname[16];
|
||||
if (mqttArr && (aJson.getArraySize(mqttArr)))
|
||||
{
|
||||
deviceName = aJson.getArrayItem(mqttArr, 0)->valuestring;
|
||||
deviceName = getStringFromConfig(mqttArr, 0);
|
||||
debugSerial<<F("Device Name:")<<deviceName<<endl;
|
||||
}
|
||||
#ifdef SYSLOG_ENABLE
|
||||
//debugSerial<<"debugSerial:";
|
||||
delay(100);
|
||||
if (udpSyslogArr && (n = aJson.getArraySize(udpSyslogArr))) {
|
||||
char *syslogServer = aJson.getArrayItem(udpSyslogArr, 0)->valuestring;
|
||||
char *syslogServer = getStringFromConfig(udpSyslogArr, 0);
|
||||
if (n>1) syslogPort = aJson.getArrayItem(udpSyslogArr, 1)->valueint;
|
||||
|
||||
inet_ntoa_r(Ethernet.localIP(),syslogDeviceHostname,sizeof(syslogDeviceHostname));
|
||||
@@ -544,11 +595,11 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
||||
|
||||
if (!mqttClient.connected() && mqttArr && ((n = aJson.getArraySize(mqttArr)) > 1)) {
|
||||
// char *client_id = aJson.getArrayItem(mqttArr, 0)->valuestring;
|
||||
char *servername = aJson.getArrayItem(mqttArr, 1)->valuestring;
|
||||
char *servername = getStringFromConfig(mqttArr, 1);
|
||||
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
||||
if (n >= 4) user = aJson.getArrayItem(mqttArr, 3)->valuestring;
|
||||
if (n >= 4) user = getStringFromConfig(mqttArr, 3);
|
||||
if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf, sizeof(passwordBuf)) && (n >= 5)) {
|
||||
password = aJson.getArrayItem(mqttArr, 4)->valuestring;
|
||||
password = getStringFromConfig(mqttArr, 4);
|
||||
debugSerial<<F("Using MQTT password from config");
|
||||
}
|
||||
|
||||
@@ -579,7 +630,7 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
||||
// wdt_en();
|
||||
configOk = true;
|
||||
// ... Temporary subscribe to status topic
|
||||
char buf[MQTT_TOPIC_LENGTH];
|
||||
char buf[MQTT_TOPIC_LENGTH+1];
|
||||
|
||||
// strncpy_P(buf, outprefix, sizeof(buf));
|
||||
setTopic(buf,sizeof(buf),T_OUT);
|
||||
@@ -681,6 +732,10 @@ wifiManager.setTimeout(30);
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
debugSerial<<F("WiFi connected. IP address: ")<<WiFi.localIP()<<endl;
|
||||
lanStatus = HAVE_IP_ADDRESS;//1;
|
||||
#ifdef OTA
|
||||
// start the OTEthernet library with internal (flash) based storage
|
||||
ArduinoOTA.begin(Ethernet.localIP(), "Lighthub", "password", InternalStorage);
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
debugSerial<<F("Problem with WiFi!");
|
||||
@@ -715,6 +770,10 @@ wifiManager.setTimeout(30);
|
||||
} else Ethernet.begin(mac, ip);
|
||||
debugSerial<<endl;
|
||||
lanStatus = HAVE_IP_ADDRESS;
|
||||
#ifdef OTA
|
||||
// start the OTEthernet library with internal (flash) based storage
|
||||
ArduinoOTA.begin(Ethernet.localIP(), "Lighthub", "password", InternalStorage);
|
||||
#endif
|
||||
#ifdef _artnet
|
||||
if (artnet) artnet->begin();
|
||||
#endif
|
||||
@@ -743,6 +802,10 @@ wifiManager.setTimeout(30);
|
||||
debugSerial<<F("Got IP address:");
|
||||
printIPAddress(Ethernet.localIP());
|
||||
lanStatus = HAVE_IP_ADDRESS;//1;
|
||||
#ifdef OTA
|
||||
// start the OTEthernet library with internal (flash) based storage
|
||||
ArduinoOTA.begin(Ethernet.localIP(), "Lighthub", "password", InternalStorage);
|
||||
#endif
|
||||
#ifdef _artnet
|
||||
if (artnet) artnet->begin();
|
||||
#endif
|
||||
@@ -781,7 +844,7 @@ void Changed(int i, DeviceAddress addr, float currentTemp) {
|
||||
debugSerial<<endl<<F("T:")<<valstr<<F("<");
|
||||
aJsonObject *owObj = aJson.getObjectItem(owArr, addrstr);
|
||||
if (owObj) {
|
||||
owEmitString = aJson.getObjectItem(owObj, "emit")->valuestring;
|
||||
owEmitString = getStringFromConfig(owObj, "emit");
|
||||
debugSerial<<owEmitString<<F(">")<<endl;
|
||||
if ((currentTemp != -127.0) && (currentTemp != 85.0) && (currentTemp != 0.0))
|
||||
{
|
||||
@@ -790,7 +853,7 @@ void Changed(int i, DeviceAddress addr, float currentTemp) {
|
||||
|
||||
#ifdef WITH_DOMOTICZ
|
||||
aJsonObject *idx = aJson.getObjectItem(owObj, "idx");
|
||||
if (idx && idx->valuestring) {//DOMOTICZ json format support
|
||||
if (idx && && idx->type ==aJson_String && idx->valuestring) {//DOMOTICZ json format support
|
||||
debugSerial << endl << idx->valuestring << F(" Domoticz valstr:");
|
||||
char valstr[50];
|
||||
sprintf(valstr, "{\"idx\":%s,\"svalue\":\"%.1f\"}", idx->valuestring, currentTemp);
|
||||
@@ -808,7 +871,7 @@ void Changed(int i, DeviceAddress addr, float currentTemp) {
|
||||
mqttClient.publish(addrstr, valstr);
|
||||
}
|
||||
// And translate temp to internal items
|
||||
owItem = aJson.getObjectItem(owObj, "item")->valuestring;
|
||||
owItem = getStringFromConfig(owObj, "item");
|
||||
if (owItem)
|
||||
thermoSetCurTemp(owItem, currentTemp); ///TODO: Refactore using Items interface
|
||||
} // if valid temperature
|
||||
@@ -860,6 +923,7 @@ void cmdFunctionReboot(int arg_cnt, char **args) {
|
||||
|
||||
void applyConfig() {
|
||||
if (!root) return;
|
||||
configLocked++;
|
||||
#ifdef _dmxin
|
||||
int itemsCount;
|
||||
dmxArr = aJson.getObjectItem(root, "dmxin");
|
||||
@@ -870,9 +934,10 @@ void applyConfig() {
|
||||
#endif
|
||||
#ifdef _dmxout
|
||||
int maxChannels;
|
||||
short numParams;
|
||||
aJsonObject *dmxoutArr = aJson.getObjectItem(root, "dmx");
|
||||
if (dmxoutArr && aJson.getArraySize(dmxoutArr) >=1 ) {
|
||||
DMXoutSetup(maxChannels = aJson.getArrayItem(dmxoutArr, 1)->valueint);
|
||||
if (dmxoutArr && (numParams=aJson.getArraySize(dmxoutArr)) >=1 ) {
|
||||
DMXoutSetup(maxChannels = aJson.getArrayItem(dmxoutArr, numParams-1)->valueint);
|
||||
debugSerial<<F("DMX out started. Channels: ")<<maxChannels<<endl;
|
||||
}
|
||||
#endif
|
||||
@@ -887,6 +952,7 @@ void applyConfig() {
|
||||
owReady = owSetup(&Changed);
|
||||
if (owReady) debugSerial<<F("One wire Ready\n");
|
||||
t_count = 0;
|
||||
|
||||
while (item && owReady) {
|
||||
if ((item->type == aJson_Object)) {
|
||||
DeviceAddress addr;
|
||||
@@ -946,6 +1012,8 @@ void applyConfig() {
|
||||
udpSyslogArr = aJson.getObjectItem(root, "syslog");
|
||||
#endif
|
||||
printConfigSummary();
|
||||
|
||||
configLocked--;
|
||||
}
|
||||
|
||||
void printConfigSummary() {
|
||||
@@ -1142,7 +1210,8 @@ void cmdFunctionPwd(int arg_cnt, char **args)
|
||||
}
|
||||
|
||||
void cmdFunctionSetMac(int arg_cnt, char **args) {
|
||||
if (sscanf(args[1], "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) < 6) {
|
||||
char dummy;
|
||||
if (sscanf(args[1], "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5], &dummy) < 6) {
|
||||
debugSerial<<F("could not parse: ")<<args[1];
|
||||
return;
|
||||
}
|
||||
@@ -1517,6 +1586,33 @@ void printFirmwareVersionAndBuildOptions() {
|
||||
#else
|
||||
debugSerial<<F("\n(-)RESTART_LAN_ON_MQTT_ERRORS");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CSSHDC_DISABLE
|
||||
debugSerial<<F("\n(-)CCS811 & HDC1080");
|
||||
#else
|
||||
debugSerial<<F("\n(+)CCS811 & HDC1080");
|
||||
#endif
|
||||
#ifndef AC_DISABLE
|
||||
debugSerial<<F("\n(+)AC HAIER");
|
||||
#else
|
||||
debugSerial<<F("\n(-)AC HAIER");
|
||||
#endif
|
||||
#ifndef MOTOR_DISABLE
|
||||
debugSerial<<F("\n(+)MOTOR CTR");
|
||||
#else
|
||||
debugSerial<<F("\n(-)MOTOR CTR");
|
||||
#endif
|
||||
#ifndef SPILED_DISABLE
|
||||
debugSerial<<F("\n(+)SPI LED");
|
||||
#else
|
||||
debugSerial<<F("\n(-)SPI LED");
|
||||
#endif
|
||||
#ifndef FASTLED
|
||||
debugSerial<<F("\n(+)FASTLED");
|
||||
#else
|
||||
debugSerial<<F("\n(+)ADAFRUIT LED");
|
||||
#endif
|
||||
debugSerial<<endl;
|
||||
|
||||
|
||||
@@ -1541,7 +1637,7 @@ void publishStat(){
|
||||
char topic[64];
|
||||
char intbuf[16];
|
||||
uint32_t ut = millis()/1000UL;
|
||||
if (!mqttClient.connected()) return;
|
||||
if (!mqttClient.connected() || ethernetIdleCount) return;
|
||||
|
||||
// debugSerial<<F("\nfree RAM: ")<<fr;
|
||||
setTopic(topic,sizeof(topic),T_DEV);
|
||||
@@ -1566,6 +1662,7 @@ for (short i = 0; i < 6; i++) {
|
||||
mac[i] = EEPROM.read(i);
|
||||
if (mac[i] != 0 && mac[i] != 0xff) isMacValid = true;
|
||||
}
|
||||
|
||||
if (!isMacValid) {
|
||||
debugSerial<<F("No MAC configured: set firmware's MAC\n");
|
||||
|
||||
@@ -1573,6 +1670,9 @@ if (!isMacValid) {
|
||||
const char *macStr = QUOTE(CUSTOM_FIRMWARE_MAC);//colon(:) separated from build options
|
||||
parseBytes(macStr, ':', mac, 6, 16);
|
||||
|
||||
mac[0]&=0xFE;
|
||||
mac[0]|=2;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
|
||||
//Using original MPU MAC
|
||||
WiFi.begin();
|
||||
@@ -1591,6 +1691,7 @@ if (!isMacValid) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
printMACAddress();
|
||||
}
|
||||
|
||||
@@ -1613,6 +1714,10 @@ void setupCmdArduino() {
|
||||
}
|
||||
|
||||
void loop_main() {
|
||||
#if defined(OTA)
|
||||
ArduinoOTA.poll();
|
||||
#endif
|
||||
|
||||
#if defined(M5STACK)
|
||||
// Initialize the M5Stack object
|
||||
M5.update();
|
||||
@@ -1637,9 +1742,9 @@ void loop_main() {
|
||||
#endif
|
||||
|
||||
if (items) {
|
||||
#ifndef MODBUS_DISABLE
|
||||
// #ifndef MODBUS_DISABLE
|
||||
if (lanStatus != RETAINING_COLLECTING) pollingLoop();
|
||||
#endif
|
||||
// #endif
|
||||
//#ifdef _owire
|
||||
thermoLoop();
|
||||
//#endif
|
||||
@@ -1705,13 +1810,14 @@ void modbusIdle(void) {
|
||||
void inputLoop(void) {
|
||||
if (!inputs) return;
|
||||
|
||||
|
||||
configLocked++;
|
||||
if (millis() > nextInputCheck) {
|
||||
aJsonObject *input = inputs->child;
|
||||
|
||||
while (input) {
|
||||
if ((input->type == aJson_Object)) {
|
||||
Input in(input);
|
||||
in.poll(CHECK_INPUT);
|
||||
in.Poll(CHECK_INPUT);
|
||||
}
|
||||
input = input->next;
|
||||
}
|
||||
@@ -1723,18 +1829,18 @@ void inputLoop(void) {
|
||||
while (input) {
|
||||
if ((input->type == aJson_Object)) {
|
||||
Input in(input);
|
||||
in.poll(CHECK_SENSOR);
|
||||
in.Poll(CHECK_SENSOR);
|
||||
}
|
||||
input = input->next;
|
||||
}
|
||||
nextSensorCheck = millis() + INTERVAL_CHECK_SENSOR;
|
||||
}
|
||||
|
||||
configLocked--;
|
||||
}
|
||||
|
||||
void inputSetup(void) {
|
||||
if (!inputs) return;
|
||||
|
||||
configLocked++;
|
||||
aJsonObject *input = inputs->child;
|
||||
while (input) {
|
||||
if ((input->type == aJson_Object)) {
|
||||
@@ -1743,19 +1849,40 @@ void inputSetup(void) {
|
||||
}
|
||||
input = input->next;
|
||||
}
|
||||
configLocked--;
|
||||
}
|
||||
|
||||
//#ifndef MODBUS_DISABLE
|
||||
|
||||
void pollingLoop(void) {
|
||||
// FAST POLLINT - as often AS possible every item
|
||||
configLocked++;
|
||||
if (items) {
|
||||
aJsonObject * item = items->child;
|
||||
while (items && item)
|
||||
if (item->type == aJson_Array && aJson.getArraySize(item)>1) {
|
||||
Item it(item);
|
||||
if (it.isValid()) {
|
||||
it.Poll(POLLING_FAST);
|
||||
} //isValid
|
||||
item = item->next;
|
||||
} //if
|
||||
}
|
||||
configLocked--;
|
||||
// SLOW POLLING
|
||||
boolean done = false;
|
||||
if (lanStatus == RETAINING_COLLECTING) return;
|
||||
if (millis() > nextPollingCheck) {
|
||||
while (pollingItem && !done) {
|
||||
if (pollingItem->type == aJson_Array) {
|
||||
Item it(pollingItem);
|
||||
nextPollingCheck = millis() + it.Poll(); //INTERVAL_CHECK_MODBUS;
|
||||
done = true;
|
||||
uint32_t ret = it.Poll(POLLING_SLOW);
|
||||
if (ret)
|
||||
{
|
||||
nextPollingCheck = millis() + ret; //INTERVAL_CHECK_MODBUS;
|
||||
done = true;
|
||||
}
|
||||
}//if
|
||||
if (!pollingItem) return; //Config was re-readed
|
||||
pollingItem = pollingItem->next;
|
||||
if (!pollingItem) {
|
||||
pollingItem = items->child;
|
||||
@@ -1764,7 +1891,6 @@ void pollingLoop(void) {
|
||||
} //while
|
||||
}//if
|
||||
}
|
||||
//#endif
|
||||
|
||||
bool isThermostatWithMinArraySize(aJsonObject *item, int minimalArraySize) {
|
||||
return (item->type == aJson_Array) && (aJson.getArrayItem(item, I_TYPE)->valueint == CH_THERMO) &&
|
||||
@@ -1790,6 +1916,7 @@ void thermoLoop(void) {
|
||||
return;
|
||||
if (!items) return;
|
||||
bool thermostatCheckPrinted = false;
|
||||
configLocked++;
|
||||
for (aJsonObject *thermoItem = items->child; thermoItem; thermoItem = thermoItem->next) {
|
||||
if (isThermostatWithMinArraySize(thermoItem, 5)) {
|
||||
aJsonObject *thermoExtensionArray = aJson.getArrayItem(thermoItem, I_EXT);
|
||||
@@ -1814,17 +1941,17 @@ void thermoLoop(void) {
|
||||
<< F(" cmd:") << thermoStateCommand;
|
||||
if (thermoPin<0) pinMode(-thermoPin, OUTPUT); else pinMode(thermoPin, OUTPUT);
|
||||
if (thermoDisabledOrDisconnected(thermoExtensionArray, thermoStateCommand)) {
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, LOW); digitalWrite(thermoPin, LOW);
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, LOW); else digitalWrite(thermoPin, LOW);
|
||||
// Caution - for water heaters (negative pin#) if some comes wrong (or no connection with termometers output is LOW - valve OPEN)
|
||||
// OFF - also VALVE is OPEN (no teat control)
|
||||
debugSerial<<F(" OFF");
|
||||
} else {
|
||||
if (curTemp < thermoSetting - THERMO_GIST_CELSIUS) {
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, LOW); digitalWrite(thermoPin, HIGH);
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, LOW); else digitalWrite(thermoPin, HIGH);
|
||||
debugSerial<<F(" ON");
|
||||
} //too cold
|
||||
else if (curTemp >= thermoSetting) {
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, HIGH); digitalWrite(thermoPin, LOW);
|
||||
if (thermoPin<0) digitalWrite(-thermoPin, HIGH); else digitalWrite(thermoPin, LOW);
|
||||
debugSerial<<F(" OFF");
|
||||
} //Reached settings
|
||||
else debugSerial<<F(" -target zone-"); // Nothing to do
|
||||
@@ -1833,7 +1960,7 @@ void thermoLoop(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configLocked--;
|
||||
nextThermostatCheck = millis() + THERMOSTAT_CHECK_PERIOD;
|
||||
publishStat();
|
||||
#ifndef DISABLE_FREERAM_PRINT
|
||||
|
||||
+7
-5
@@ -21,6 +21,7 @@
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP8266)
|
||||
#include <FS.h> //this needs to be first, or it all crashes and burns...
|
||||
//#include "SPIFFS.h"
|
||||
#include <ESP_EEPROM.h>
|
||||
#include <ESP8266HTTPClient.h>
|
||||
//#include <ArduinoHttpClient.h>
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
#if defined ARDUINO_ARCH_ESP32
|
||||
#include <FS.h> //this needs to be first, or it all crashes and burns...
|
||||
//#include "SPIFFS.h"
|
||||
//#include <EEPROM.h>
|
||||
#include <NRFFlashStorage.h>
|
||||
//#include "HttpClient.h"
|
||||
@@ -121,9 +123,9 @@
|
||||
#include <ModbusMaster.h>
|
||||
#endif
|
||||
|
||||
#ifndef DMX_DISABLE
|
||||
#include "FastLED.h"
|
||||
#endif
|
||||
//#ifndef DMX_DISABLE
|
||||
//#include "FastLED.h"
|
||||
//#endif
|
||||
|
||||
#ifdef _owire
|
||||
#include "owTerm.h"
|
||||
@@ -171,8 +173,8 @@ enum lan_status {
|
||||
INITIAL_STATE = 0,
|
||||
HAVE_IP_ADDRESS = 1,
|
||||
IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER = 2,
|
||||
OPERATION = 3,
|
||||
RETAINING_COLLECTING = 4,
|
||||
RETAINING_COLLECTING = 3,
|
||||
OPERATION = 4,
|
||||
AWAITING_ADDRESS = -10,
|
||||
RECONNECT = 12,
|
||||
READ_RE_CONFIG = -11,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "Arduino.h"
|
||||
#include "options.h"
|
||||
#include "Streaming.h"
|
||||
#include "item.h"
|
||||
|
||||
#if defined(M5STACK)
|
||||
#include <M5Stack.h>
|
||||
@@ -33,9 +34,12 @@ Wire.begin(); //Inialize I2C Harware
|
||||
//It is recommended to check return status on .begin(), but it is not
|
||||
//required.
|
||||
CCS811Core::status returnCode = ccs811.begin();
|
||||
//CCS811Core::CC811_Status_e returnCode = ccs811.beginWithStatus();
|
||||
if (returnCode != CCS811Core::SENSOR_SUCCESS)
|
||||
//if (returnCode != CCS811Core::CCS811_Stat_SUCCESS)
|
||||
{
|
||||
Serial.println("CCS811 Init error");
|
||||
Serial.print("CCS811 Init error ");
|
||||
//Serial.println(ccs811.statusString(returnCode));
|
||||
printDriverError(returnCode);
|
||||
return 0;
|
||||
}
|
||||
@@ -72,17 +76,18 @@ return 1;
|
||||
|
||||
void i2cReset(){
|
||||
Wire.endTransmission(true);
|
||||
#if defined (ARDUINO_ARCH_ESP8266)
|
||||
#if defined (SCL_RESET)
|
||||
SCL_LOW();
|
||||
delay(300);
|
||||
SCL_HIGH();
|
||||
#endif
|
||||
}
|
||||
|
||||
int in_hdc1080::Poll()
|
||||
int in_hdc1080::Poll(short cause)
|
||||
{
|
||||
float h,t;
|
||||
int reg;
|
||||
if (cause!=POLLING_SLOW) return 0;
|
||||
if (!HDC1080ready) {debugSerial<<F("HDC1080 not initialized")<<endl; return 0;}
|
||||
Serial.print("HDC Status=");
|
||||
Serial.println(reg=hdc1080.readRegister().rawData,HEX);
|
||||
@@ -115,10 +120,10 @@ else //ESP I2C glitch
|
||||
Serial.println("I2C Reset");
|
||||
i2cReset();
|
||||
}
|
||||
return 1;
|
||||
return INTERVAL_POLLING;
|
||||
}
|
||||
|
||||
int in_ccs811::Poll()
|
||||
int in_ccs811::Poll(short cause)
|
||||
{
|
||||
if (!CCS811ready) {debugSerial<<F("ccs811 not initialized")<<endl; return 0;}
|
||||
#ifdef WAK_PIN
|
||||
|
||||
@@ -18,8 +18,17 @@
|
||||
|
||||
#define SCL_LOW() (GPES = (1 << twi_scl))
|
||||
#define SCL_HIGH() (GPEC = (1 << twi_scl))
|
||||
#define SCL_RESET
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if defined (__SAM3X8E__)
|
||||
#define SCL_LOW() digitalWrite(21,LOW)
|
||||
#define SCL_HIGH() digitalWrite(21,HIGH)
|
||||
#define SCL_RESET
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if defined (ARDUINO_ARCH_ESP32)
|
||||
#undef WAK_PIN
|
||||
//#ifndef WAK_PIN
|
||||
@@ -41,7 +50,7 @@ public:
|
||||
//uint16_t ccs811Baseline;
|
||||
in_ccs811(Input * _in):abstractIn(_in){};
|
||||
int Setup() override;
|
||||
int Poll() override;
|
||||
int Poll(short cause) override;
|
||||
|
||||
protected:
|
||||
void printDriverError( CCS811Core::status errorCode );
|
||||
@@ -53,7 +62,7 @@ public:
|
||||
//ClosedCube_HDC1080 hdc1080;
|
||||
in_hdc1080(Input * _in):abstractIn(_in){};
|
||||
int Setup() override;
|
||||
int Poll() override;
|
||||
int Poll(short cause) override;
|
||||
|
||||
protected:
|
||||
void printSerialNumber();
|
||||
|
||||
@@ -233,8 +233,10 @@ int out_AC::isActive()
|
||||
return (power & 1);
|
||||
}
|
||||
|
||||
int out_AC::Poll()
|
||||
int out_AC::Poll(short cause)
|
||||
{
|
||||
if (cause!=POLLING_SLOW) return 0;
|
||||
|
||||
long now = millis();
|
||||
if (now - prevPolling > INTERVAL_AC_POLLING) {
|
||||
prevPolling = now;
|
||||
@@ -253,7 +255,7 @@ delay(100);
|
||||
InsertData(data, 37);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return INTERVAL_POLLING;
|
||||
};
|
||||
|
||||
int out_AC::Ctrl(short cmd, short n, int * Parameters, boolean send, int suffixCode, char* subItem)
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
|
||||
out_AC(Item * _item):abstractOut(_item){};
|
||||
int Setup() override;
|
||||
int Poll() override;
|
||||
int Poll(short cause) override;
|
||||
int Stop() override;
|
||||
int Status() override;
|
||||
int isActive() override;
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
#ifndef MOTOR_DISABLE
|
||||
|
||||
#include "modules/out_motor.h"
|
||||
#include "Arduino.h"
|
||||
#include "options.h"
|
||||
#include "Streaming.h"
|
||||
|
||||
#include "item.h"
|
||||
|
||||
static int driverStatus = CST_UNKNOWN;
|
||||
|
||||
void out_Motor::getConfig()
|
||||
{
|
||||
pinUp=item->getArg(0);
|
||||
if(pinUp<=0 || pinUp>=PINS_COUNT) pinUp=32;
|
||||
|
||||
pinDown=item->getArg(1);
|
||||
if (pinDown<=0 || pinDown>=PINS_COUNT) pinDown=33;
|
||||
|
||||
pinFeedback=item->getArg(2);
|
||||
if (pinFeedback<0 || pinFeedback>=PINS_COUNT) pinFeedback=0;
|
||||
|
||||
feedbackOpen=item->getArg(3);
|
||||
if (feedbackOpen<=0 || feedbackOpen>1024) feedbackOpen=0;
|
||||
|
||||
feedbackClosed=item->getArg(4);
|
||||
if (feedbackClosed<0 || feedbackClosed>1024) feedbackClosed=1024;
|
||||
|
||||
maxOnTime=item->getArg(5);
|
||||
if (maxOnTime<=0) maxOnTime=10000;
|
||||
}
|
||||
|
||||
|
||||
int out_Motor::Setup()
|
||||
{
|
||||
getConfig();
|
||||
Serial.println("Motor Init");
|
||||
pinMode(pinUp,OUTPUT);
|
||||
pinMode(pinDown,OUTPUT);
|
||||
digitalWrite(pinUp,LOW);
|
||||
digitalWrite(pinDown,LOW);
|
||||
pinMode(pinFeedback, INPUT);
|
||||
item->setExt(0);
|
||||
item->clearFlag(ACTION_NEEDED);
|
||||
item->clearFlag(ACTION_IN_PROCESS);
|
||||
driverStatus = CST_INITIALIZED;
|
||||
motorQuote = MOTOR_QUOTE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int out_Motor::Stop()
|
||||
{
|
||||
Serial.println("Motor De-Init");
|
||||
digitalWrite(pinUp,LOW);
|
||||
digitalWrite(pinDown,LOW);
|
||||
item->setExt(0);
|
||||
driverStatus = CST_UNKNOWN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int out_Motor::Status()
|
||||
{
|
||||
return driverStatus;
|
||||
}
|
||||
|
||||
int out_Motor::isActive()
|
||||
{
|
||||
return item->getVal();
|
||||
}
|
||||
|
||||
int out_Motor::Poll(short cause)
|
||||
{
|
||||
int curPos = -1;
|
||||
int targetPos = -1;
|
||||
int dif;
|
||||
if (!item->getFlag(ACTION_NEEDED)) return 0;
|
||||
|
||||
if (!item->getFlag(ACTION_IN_PROCESS))
|
||||
{
|
||||
if (motorQuote)
|
||||
{
|
||||
item->setFlag(ACTION_IN_PROCESS);
|
||||
motorQuote--;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
uint32_t motorOfftime = item->getExt();
|
||||
|
||||
switch (item->getCmd())
|
||||
{
|
||||
case CMD_ON:
|
||||
case CMD_XON:
|
||||
targetPos = item->getVal();
|
||||
break;
|
||||
|
||||
case CMD_OFF:
|
||||
case CMD_HALT:
|
||||
targetPos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pinFeedback && isAnalogPin(pinFeedback))
|
||||
{
|
||||
curPos=map(analogRead(pinFeedback),feedbackClosed,feedbackOpen,0,100);
|
||||
if (curPos<0) curPos=0;
|
||||
if (curPos>100) curPos=100;
|
||||
}
|
||||
|
||||
if (motorOfftime && motorOfftime<millis()) //Time over
|
||||
{dif = 0; debugSerial<<F("Motor timeout")<<endl;}
|
||||
else if (curPos>=0)
|
||||
dif=targetPos-curPos;
|
||||
else
|
||||
dif=targetPos-50; // Have No feedback
|
||||
|
||||
|
||||
|
||||
if (dif<-POS_ERR)
|
||||
{
|
||||
|
||||
digitalWrite(pinDown,LOW);
|
||||
if (!item->getExt())item->setExt(millis()+maxOnTime);
|
||||
|
||||
//
|
||||
//PINS_COUNT
|
||||
//PIN_ATTR_ANALOG
|
||||
// uint32_t attr = g_APinDescription[pinUp].ulPinAttribute;
|
||||
// if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) ;
|
||||
#ifndef ESP32
|
||||
if (digitalPinHasPWM(pinUp))
|
||||
{
|
||||
//Serial.println("pinUP PWM");
|
||||
int velocity = map(-dif, 0, 10, 0, 255);
|
||||
if (velocity>255) velocity=255;
|
||||
if (velocity<0) velocity=0;
|
||||
analogWrite(pinUp,velocity);
|
||||
}
|
||||
|
||||
else if (digitalPinHasPWM(pinDown))
|
||||
{
|
||||
// Serial.println("pinDown PWM fallback");
|
||||
digitalWrite(pinUp,HIGH);
|
||||
int velocity = map(-dif, 0, 10, 255, 0);
|
||||
if (velocity>255) velocity=255;
|
||||
if (velocity<0) velocity=0;
|
||||
analogWrite(pinDown,velocity);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Serial.print(pinUp);
|
||||
// Serial.println(" pinUP noPWM");
|
||||
digitalWrite(pinUp,HIGH);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (dif>POS_ERR)
|
||||
{
|
||||
digitalWrite(pinUp,LOW);
|
||||
|
||||
if (!item->getExt()) item->setExt(millis()+maxOnTime);
|
||||
#ifndef ESP32
|
||||
if (digitalPinHasPWM(pinDown))
|
||||
{
|
||||
//Serial.println("pinDown PWM");
|
||||
int velocity = map(dif, 0, 10, 0, 255);
|
||||
if (velocity>255) velocity=255;
|
||||
if (velocity<0) velocity=0;
|
||||
analogWrite(pinDown,velocity);
|
||||
}
|
||||
else
|
||||
if (digitalPinHasPWM(pinUp))
|
||||
{
|
||||
//Serial.println("pinUP PWM fallback");
|
||||
digitalWrite(pinDown,HIGH);
|
||||
int velocity = map(dif, 0, 10, 255, 0);
|
||||
if (velocity>255) velocity=255;
|
||||
if (velocity<0) velocity=0;
|
||||
analogWrite(pinUp,velocity);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//Serial.print(pinDown);
|
||||
//Serial.println(" pinDown noPWM");
|
||||
digitalWrite(pinDown,HIGH);
|
||||
}
|
||||
|
||||
}
|
||||
else //Target zone
|
||||
{ Serial.println("Target");
|
||||
digitalWrite(pinUp,LOW);
|
||||
digitalWrite(pinDown,LOW);
|
||||
item->setExt(0);
|
||||
item->clearFlag(ACTION_NEEDED);
|
||||
item->clearFlag(ACTION_IN_PROCESS);
|
||||
motorQuote++;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int out_Motor::getChanType()
|
||||
{
|
||||
return CH_PWM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int out_Motor::Ctrl(short cmd, short n, int * Parameters, boolean send, int suffixCode, char* subItem)
|
||||
{
|
||||
int chActive = item->isActive();
|
||||
bool toExecute = (chActive>0);
|
||||
long st;
|
||||
if (cmd>0 && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
|
||||
|
||||
item->setFlag(ACTION_NEEDED);
|
||||
|
||||
switch(suffixCode)
|
||||
{
|
||||
case S_NOTFOUND:
|
||||
// turn on and set
|
||||
toExecute = true;
|
||||
debugSerial<<F("Forced execution");
|
||||
case S_SET:
|
||||
if (!Parameters || n==0) return 0;
|
||||
item->setVal(st=Parameters[0]); //Store
|
||||
if (!suffixCode)
|
||||
{
|
||||
if (chActive>0 && !st) item->setCmd(CMD_OFF);
|
||||
if (chActive==0 && st) item->setCmd(CMD_ON);
|
||||
item->SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED);
|
||||
if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time
|
||||
}
|
||||
else item->SendStatus(SEND_PARAMETERS | SEND_DEFFERED);
|
||||
|
||||
return 1;
|
||||
//break;
|
||||
|
||||
case S_CMD:
|
||||
item->setCmd(cmd);
|
||||
switch (cmd)
|
||||
{
|
||||
case CMD_ON:
|
||||
//retrive stored values
|
||||
st = item->getVal();
|
||||
|
||||
|
||||
if (st && (st<MIN_VOLUME) && send) st=INIT_VOLUME;
|
||||
item->setVal(st);
|
||||
|
||||
if (st) //Stored smthng
|
||||
{
|
||||
if (send) item->SendStatus(SEND_COMMAND | SEND_PARAMETERS);
|
||||
debugSerial<<F("Restored: ")<<st<<endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugSerial<<st<<F(": No stored values - default\n");
|
||||
// Store
|
||||
st=100;
|
||||
item->setVal(st);
|
||||
if (send) item->SendStatus(SEND_COMMAND | SEND_PARAMETERS );
|
||||
}
|
||||
if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time
|
||||
return 1;
|
||||
|
||||
case CMD_OFF:
|
||||
if (send) item->SendStatus(SEND_COMMAND);
|
||||
if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time
|
||||
return 1;
|
||||
|
||||
} //switch cmd
|
||||
|
||||
break;
|
||||
} //switch suffix
|
||||
debugSerial<<F("Unknown cmd")<<endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "options.h"
|
||||
#ifndef MOTOR_DISABLE
|
||||
#include <abstractout.h>
|
||||
#include <item.h>
|
||||
|
||||
#ifndef POS_ERR
|
||||
#define POS_ERR 2
|
||||
#endif
|
||||
|
||||
// The number of simultaniusly working motors
|
||||
#ifndef MOTOR_QUOTE
|
||||
#define MOTOR_QUOTE 2
|
||||
#endif
|
||||
|
||||
static int8_t motorQuote = MOTOR_QUOTE;
|
||||
|
||||
class out_Motor : public abstractOut {
|
||||
public:
|
||||
|
||||
out_Motor(Item * _item):abstractOut(_item){getConfig();};
|
||||
int Setup() override;
|
||||
int Poll(short cause) override;
|
||||
int Stop() override;
|
||||
int Status() override;
|
||||
int isActive() override;
|
||||
int getChanType() override;
|
||||
int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true, int suffixCode=0, char* subItem=NULL) override;
|
||||
|
||||
int8_t pinUp;
|
||||
int8_t pinDown;
|
||||
int8_t pinFeedback;
|
||||
int16_t maxOnTime;
|
||||
uint16_t feedbackOpen;
|
||||
uint16_t feedbackClosed;
|
||||
protected:
|
||||
void getConfig();
|
||||
};
|
||||
#endif
|
||||
+285
-47
@@ -4,19 +4,63 @@
|
||||
#include "Arduino.h"
|
||||
#include "options.h"
|
||||
#include "Streaming.h"
|
||||
#include "FastLED.h"
|
||||
|
||||
#include "item.h"
|
||||
|
||||
#define NUM_LEDS 15
|
||||
#define DATA_PIN 4
|
||||
#ifdef ADAFRUIT_LED
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
|
||||
#endif
|
||||
Adafruit_NeoPixel *leds = NULL;
|
||||
|
||||
#else
|
||||
#include "FastLED.h"
|
||||
static CRGB *leds = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
#define NUM_LEDS 43
|
||||
|
||||
static CRGB leds[NUM_LEDS];
|
||||
static int driverStatus = CST_UNKNOWN;
|
||||
|
||||
void out_SPILed::getConfig()
|
||||
{
|
||||
pin=item->getArg(0);
|
||||
if(pin<=0) pin=3;
|
||||
|
||||
numLeds=item->getArg(1);
|
||||
if (numLeds<=0) numLeds=NUM_LEDS;
|
||||
|
||||
ledsType=item->getArg(2);
|
||||
#ifdef ADAFRUIT_LED
|
||||
if (ledsType<=0) ledsType= NEO_BRG + NEO_KHZ800;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int out_SPILed::Setup()
|
||||
{
|
||||
getConfig();
|
||||
Serial.println("SPI-LED Init");
|
||||
FastLED.addLeds<TM1809, DATA_PIN, BRG>(leds, NUM_LEDS);
|
||||
|
||||
if (!leds)
|
||||
{
|
||||
#ifdef ADAFRUIT_LED
|
||||
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
|
||||
clock_prescale_set(clock_div_1);
|
||||
#endif
|
||||
leds = new Adafruit_NeoPixel(numLeds, pin, ledsType);
|
||||
leds->begin();
|
||||
#else
|
||||
leds = new CRGB [numLeds]; //Allocate dynamic memory for LED objects
|
||||
//template< CONTROLLER = TM1809, uint8_t DATA_PIN = pin, EOrder ORDER = BRG >
|
||||
//FastLED.addLeds<TM1809, pin, BRG>(leds, numLeds);
|
||||
FastLED.addLeds<CONTROLLER, DATA_PIN, ORDER>(leds, numLeds);
|
||||
#endif
|
||||
}
|
||||
|
||||
driverStatus = CST_INITIALIZED;
|
||||
return 1;
|
||||
}
|
||||
@@ -25,8 +69,15 @@ int out_SPILed::Stop()
|
||||
{
|
||||
Serial.println("SPI-LED De-Init");
|
||||
//FastLED.addLeds<TM1809, DATA_PIN, BRG>(leds, NUM_LEDS);
|
||||
#ifdef ADAFRUIT_LED
|
||||
leds->clear();
|
||||
delete leds;
|
||||
#else
|
||||
FastLED.clear(true);
|
||||
delete [] leds;
|
||||
#endif
|
||||
driverStatus = CST_UNKNOWN;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -37,61 +88,248 @@ return driverStatus;
|
||||
|
||||
int out_SPILed::isActive()
|
||||
{
|
||||
|
||||
CHstore st;
|
||||
st.aslong = item->getVal(); //Restore old params
|
||||
debugSerial<< F(" val:")<<st.v<<endl;
|
||||
return st.v;
|
||||
}
|
||||
|
||||
int out_SPILed::Poll()
|
||||
int out_SPILed::Poll(short cause)
|
||||
{
|
||||
//FastLED.show();
|
||||
return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
int out_SPILed::getChanType()
|
||||
{
|
||||
if ((ledsType>>4) == (ledsType>>6))
|
||||
return CH_RGB;
|
||||
else
|
||||
return CH_RGBW;
|
||||
}
|
||||
|
||||
int out_SPILed::PixelCtrl(CHstore *st, short cmd, int from, int to, bool show, bool rgb)
|
||||
{
|
||||
//debugSerial<<F("cmd: ")<<cmd<<endl;
|
||||
#ifdef ADAFRUIT_LED
|
||||
uint32_t pixel;
|
||||
#else
|
||||
CRGB pixel;
|
||||
#endif
|
||||
if (!rgb)
|
||||
{
|
||||
int Saturation = map(st->s, 0, 100, 0, 255);
|
||||
int Value = map(st->v, 0, 100, 0, 255);
|
||||
|
||||
#ifdef ADAFRUIT_LED
|
||||
uint16_t Hue = map(st->h, 0, 365, 0, 65535);
|
||||
pixel = leds->ColorHSV(Hue, Saturation, Value);
|
||||
#else
|
||||
int Hue = map(st->h, 0, 365, 0, 255);
|
||||
pixel = CHSV(Hue, Saturation, Value);
|
||||
#endif
|
||||
|
||||
debugSerial<<F("hsv: ")<<st->h<<F(",")<<st->s<<F(",")<<st->v<<endl;
|
||||
}
|
||||
if (to>numLeds-1) to=numLeds-1;
|
||||
if (from<0) from=0;
|
||||
|
||||
for (int i=from;i<=to;i++)
|
||||
{
|
||||
switch (cmd) {
|
||||
case CMD_ON:
|
||||
|
||||
#ifdef ADAFRUIT_LED
|
||||
if (!leds->getPixelColor(i)) leds->setPixelColor(i, leds->Color(255, 255, 255));
|
||||
#else
|
||||
if (!leds[i].r && !leds[i].g &&!leds[i].b) leds[i] = CRGB::White;
|
||||
#endif
|
||||
|
||||
|
||||
break;
|
||||
case CMD_OFF:
|
||||
#ifdef ADAFRUIT_LED
|
||||
leds->setPixelColor(i, leds->Color(0, 0, 0));
|
||||
#else
|
||||
leds[i] = CRGB::Black;
|
||||
#endif
|
||||
|
||||
break;
|
||||
default:
|
||||
if (rgb)
|
||||
{
|
||||
#ifdef ADAFRUIT_LED
|
||||
leds->setPixelColor(i, leds->Color(st->r,st->g,st->b));
|
||||
#else
|
||||
leds[i] = CRGB(st->r,st->g,st->b);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ADAFRUIT_LED
|
||||
leds->setPixelColor(i, pixel);
|
||||
#else
|
||||
leds[i] = pixel;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} //for
|
||||
if (show)
|
||||
{
|
||||
#ifdef ADAFRUIT_LED
|
||||
leds->show();
|
||||
#else
|
||||
FastLED.show();
|
||||
#endif
|
||||
|
||||
debugSerial<<F("Show")<<endl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int out_SPILed::Ctrl(short cmd, short n, int * Parameters, boolean send, int suffixCode, char* subItem)
|
||||
{
|
||||
int from=0, to=NUM_LEDS-1;
|
||||
int chActive = item->isActive();
|
||||
bool toExecute = (chActive>0);
|
||||
CHstore st;
|
||||
if (cmd>0 && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
|
||||
|
||||
int from=0, to=numLeds-1; //All LEDs on the strip by default
|
||||
// retrive LEDs range from suffix
|
||||
if (subItem)
|
||||
{ //Just single LED to control
|
||||
from=atoi(subItem);
|
||||
to=from;
|
||||
{ //Just single LED to control todo - range
|
||||
// debugSerial<<F("Range:")<<subItem<<endl;
|
||||
if (sscanf(subItem,"%d-%d",&from,&to) == 1) to=from;
|
||||
}
|
||||
debugSerial<<from<<F("-")<<to<<F(" cmd=")<<cmd<<endl;
|
||||
for (int i=from;i<=to;i++)
|
||||
{
|
||||
// debugSerial<<F(".");
|
||||
switch(cmd)
|
||||
{
|
||||
case CMD_ON:
|
||||
debugSerial<<F("Ch: ")<<i<<F(" White")<<endl;
|
||||
leds[i] = CRGB::White;
|
||||
break;
|
||||
case CMD_OFF:
|
||||
debugSerial<<F("Ch: ")<<i<<F(" Black")<<endl;
|
||||
leds[i] = CRGB::Black;
|
||||
break;
|
||||
case CMD_NUM:
|
||||
switch (suffixCode)
|
||||
{
|
||||
|
||||
// case S_POWER:
|
||||
// case S_VOL:
|
||||
//leds[n].setBrightness(Parameters[0]);
|
||||
// break;
|
||||
case S_SET:
|
||||
case S_HSV:
|
||||
debugSerial<<F("HSV: ")<<i<<F(" :")<<Parameters[0]<<Parameters[1]<<Parameters[2]<<endl;
|
||||
leds[i] = CHSV(Parameters[0],Parameters[1],Parameters[2]);
|
||||
break;
|
||||
case S_RGB:
|
||||
debugSerial<<F("RGB: ")<<i<<F(" :")<<Parameters[0]<<Parameters[1]<<Parameters[2]<<endl;
|
||||
leds[i] = CRGB(Parameters[0],Parameters[1],Parameters[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
FastLED.show();
|
||||
debugSerial<<F("Show ")<<endl;
|
||||
|
||||
switch(suffixCode)
|
||||
{
|
||||
case S_NOTFOUND:
|
||||
// turn on and set
|
||||
toExecute = true;
|
||||
case S_SET:
|
||||
case S_HSV:
|
||||
st.aslong = item->getVal(); //Restore old params
|
||||
switch (n) //How many parameters are passed?
|
||||
{
|
||||
case 1:
|
||||
st.v = Parameters[0]; //Volume only
|
||||
if (!st.hsv_flag)
|
||||
{
|
||||
st.h = 0; //Filling by default
|
||||
st.s = 0;
|
||||
st.hsv_flag = 1; // Mark stored vals as HSV
|
||||
}
|
||||
break;
|
||||
case 2: // Just hue and saturation
|
||||
st.h = Parameters[0];
|
||||
st.s = Parameters[1];
|
||||
st.hsv_flag = 1;
|
||||
break;
|
||||
case 3: //complete triplet
|
||||
st.h = Parameters[0];
|
||||
st.s = Parameters[1];
|
||||
st.v = Parameters[2];
|
||||
st.hsv_flag = 1;
|
||||
}
|
||||
PixelCtrl(&st,0,from,to,toExecute);
|
||||
|
||||
if (!subItem) //Whole strip
|
||||
{
|
||||
item->setVal(st.aslong); //Store
|
||||
if (!suffixCode)
|
||||
{
|
||||
if (chActive>0 && !st.v) item->setCmd(CMD_OFF);
|
||||
if (chActive==0 && st.v) item->setCmd(CMD_ON);
|
||||
item->SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED);
|
||||
}
|
||||
else item->SendStatus(SEND_PARAMETERS | SEND_DEFFERED);
|
||||
}
|
||||
return 1;
|
||||
//break;
|
||||
case S_RGB:
|
||||
st.r = Parameters[0];
|
||||
st.g = Parameters[1];
|
||||
st.b = Parameters[2];
|
||||
st.w = 0;
|
||||
st.hsv_flag = 0;
|
||||
PixelCtrl(&st,0,from,to,toExecute,true);
|
||||
//item->setVal(st.aslong); //Store
|
||||
if (!suffixCode)
|
||||
{
|
||||
if (chActive>0 && !st.aslong) item->setCmd(CMD_OFF);
|
||||
if (chActive==0 && st.aslong) item->setCmd(CMD_ON);
|
||||
item->SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED);
|
||||
}
|
||||
else item->SendStatus(SEND_PARAMETERS | SEND_DEFFERED);
|
||||
return 1;
|
||||
//break;
|
||||
case S_CMD:
|
||||
item->setCmd(cmd);
|
||||
switch (cmd)
|
||||
{
|
||||
case CMD_ON:
|
||||
|
||||
/*
|
||||
if (chActive>0 && send)
|
||||
{
|
||||
SendStatus(SEND_COMMAND);
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
//retrive stored values
|
||||
st.aslong = item->getVal();
|
||||
|
||||
if (subItem) // LED range, not whole strip
|
||||
PixelCtrl(&st,CMD_ON,from,to);
|
||||
else //whole strip
|
||||
{
|
||||
if (st.aslong && (st.v<MIN_VOLUME) && send) st.v=INIT_VOLUME;
|
||||
item->setVal(st.aslong);
|
||||
|
||||
if (st.aslong ) //Stored smthng
|
||||
{
|
||||
if (send) item->SendStatus(SEND_COMMAND | SEND_PARAMETERS);
|
||||
debugSerial<<F("Restored: ")<<st.h<<F(",")<<st.s<<F(",")<<st.v<<endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugSerial<<st.aslong<<F(": No stored values - default\n");
|
||||
st.h = 100;
|
||||
st.s = 0;
|
||||
st.v = 100;
|
||||
st.hsv_flag=1;
|
||||
// Store
|
||||
item->setVal(st.aslong);
|
||||
if (send) item->SendStatus(SEND_COMMAND | SEND_PARAMETERS );
|
||||
}
|
||||
|
||||
PixelCtrl(&st,0,from,to);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case CMD_OFF:
|
||||
if (subItem) // LED range, not whole strip
|
||||
PixelCtrl(&st,CMD_OFF,from,to);
|
||||
else
|
||||
{
|
||||
st.v=0;
|
||||
PixelCtrl(&st,0,from,to);
|
||||
if (send) item->SendStatus(SEND_COMMAND);
|
||||
// if (send) item->publishTopic(item->itemArr->name,"OFF","/cmd");
|
||||
}
|
||||
return 1;
|
||||
|
||||
} //switch cmd
|
||||
|
||||
break;
|
||||
} //switch suffix
|
||||
debugSerial<<F("Unknown cmd")<<endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
|
||||
#pragma once
|
||||
#include "options.h"
|
||||
#ifndef SPILED_DISABLE
|
||||
#include <abstractout.h>
|
||||
#include <item.h>
|
||||
#ifdef ADAFRUIT_LED
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#else
|
||||
#include "FastLED.h"
|
||||
#endif
|
||||
|
||||
class out_SPILed : public abstractOut {
|
||||
public:
|
||||
|
||||
out_SPILed(Item * _item):abstractOut(_item){};
|
||||
out_SPILed(Item * _item):abstractOut(_item){getConfig();};
|
||||
int Setup() override;
|
||||
int Poll() override;
|
||||
int Poll(short cause) override;
|
||||
int Stop() override;
|
||||
int Status() override;
|
||||
int isActive() override;
|
||||
int getChanType() override;
|
||||
int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true, int suffixCode=0, char* subItem=NULL) override;
|
||||
|
||||
int PixelCtrl(CHstore *st, short cmd, int from =0 , int to = 1024, bool show = 1, bool rgb = 0);
|
||||
int numLeds;
|
||||
int8_t pin;
|
||||
int ledsType;
|
||||
protected:
|
||||
void getConfig();
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
int mqtt::publish(int value)
|
||||
{};
|
||||
|
||||
int mqtt::publish(float value)
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
int mqtt::publish(char * value)
|
||||
{
|
||||
char addrstr[MQTT_TOPIC_LENGTH];
|
||||
aJsonObject *emit = aJson.getObjectItem(in, "emit");
|
||||
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
|
||||
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
|
||||
if mqttClient.connected() mqttClient.publish(addrstr, value, true);
|
||||
};
|
||||
*/
|
||||
+57
-18
@@ -1,13 +1,29 @@
|
||||
// Configuration of drivers enabled
|
||||
#ifndef PIO_SRC_REV
|
||||
#define PIO_SRC_REV v0.999
|
||||
|
||||
#ifndef FASTLED
|
||||
#define ADAFRUIT_LED
|
||||
#endif
|
||||
// ADAFRUIT library allow to dynamically configure SPI LED Strip Parameters
|
||||
|
||||
// If not defined ADAFRUIT_LED - FastLED library will be used instead
|
||||
// And strip type, pin, order must defined on compilation time
|
||||
#ifndef CONTROLLER
|
||||
#define CONTROLLER TM1809
|
||||
#endif
|
||||
|
||||
#ifndef DATA_PIN
|
||||
#define DATA_PIN 4
|
||||
#endif
|
||||
|
||||
#ifndef ORDER
|
||||
#define ORDER BRG
|
||||
#endif
|
||||
|
||||
#define TXEnablePin 13
|
||||
#define ESP_EEPROM_SIZE 2048
|
||||
|
||||
#ifndef AVR_DMXOUT_PIN
|
||||
#define AVR_DMXOUT_PIN 3
|
||||
#define AVR_DMXOUT_PIN 18
|
||||
#endif
|
||||
|
||||
#define T_ATTEMPTS 200
|
||||
@@ -19,7 +35,7 @@
|
||||
#define FM_OVERHEAT_CELSIUS 40.
|
||||
|
||||
#define MIN_VOLUME 25
|
||||
#define INIT_VOLUME 50
|
||||
#define INIT_VOLUME 40
|
||||
|
||||
#define MAXFLASHSTR 32
|
||||
#define PWDFLASHSTR 16
|
||||
@@ -35,7 +51,7 @@
|
||||
#define EEPROM_offset EEPROM_offset_NotAlligned + (4 -(EEPROM_offset_NotAlligned & 3))
|
||||
|
||||
#ifndef INTERVAL_CHECK_INPUT
|
||||
#define INTERVAL_CHECK_INPUT 50
|
||||
#define INTERVAL_CHECK_INPUT 15
|
||||
#endif
|
||||
|
||||
#ifndef INTERVAL_CHECK_SENSOR
|
||||
@@ -78,19 +94,6 @@
|
||||
#ifndef HOMETOPIC
|
||||
#define HOMETOPIC "myhome"
|
||||
#endif
|
||||
/*
|
||||
#ifndef OUTTOPIC
|
||||
#define OUTTOPIC "/myhome/s_out/"
|
||||
#endif
|
||||
|
||||
#ifndef CMDTOPIC
|
||||
#define CMDTOPIC "/myhome/in/command/"
|
||||
#endif
|
||||
|
||||
#ifndef INTOPIC
|
||||
#define INTOPIC "/myhome/in/"
|
||||
#endif
|
||||
*/
|
||||
|
||||
//Default output topic
|
||||
#ifndef OUTTOPIC
|
||||
@@ -131,6 +134,8 @@
|
||||
#define LAN_INIT_DELAY 500
|
||||
#endif
|
||||
|
||||
#define DEFAULT_INC_STEP 5
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
//All options available
|
||||
#ifdef CONTROLLINO
|
||||
@@ -202,6 +207,10 @@
|
||||
#define strncpy_P strncpy
|
||||
#endif
|
||||
|
||||
#ifndef DMX_SMOOTH_DELAY
|
||||
#define DMX_SMOOTH_DELAY 10
|
||||
#endif
|
||||
|
||||
//#ifdef M5STACK
|
||||
//#define debugSerial M5.Lcd
|
||||
//#endif
|
||||
@@ -215,3 +224,33 @@
|
||||
#else
|
||||
#define W5500_ETHERNET_SHIELD
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
#define PINS_COUNT NUM_DIGITAL_PINS
|
||||
#define isAnalogPin(p) ((p >= 54) && (p<=69))
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
#define isAnalogPin(p) (g_APinDescription[p].ulPinAttribute & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_STM32)
|
||||
#define PINS_COUNT NUM_DIGITAL_PINS
|
||||
#define isAnalogPin(p) ((p >= 44) && (p<=57))
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define PINS_COUNT NUM_DIGITAL_PINS
|
||||
#define isAnalogPin(p) ( p ==17 )
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#define PINS_COUNT NUM_DIGITAL_PINS
|
||||
#define isAnalogPin(p) ((p ==4) || (p>=12)&& (p<=15) || (p>=25)&& (p<=27)||(p>=32)&& (p<=33) || (p>=37)&& (p<=38))
|
||||
#endif
|
||||
|
||||
#if defined(NRF5)
|
||||
#define PINS_COUNT NUM_DIGITAL_PINS
|
||||
#define isAnalogPin(p) ((p >= 14) && (p<=21))
|
||||
#endif
|
||||
|
||||
+21
-4
@@ -42,9 +42,13 @@ owChangedType owChanged;
|
||||
int owUpdate() {
|
||||
#ifndef OWIRE_DISABLE
|
||||
unsigned long finish = millis() + OW_UPDATE_INTERVAL;
|
||||
short sr;
|
||||
|
||||
|
||||
/*
|
||||
if (oneWire->getError() == DS2482_ERROR_SHORT)
|
||||
{
|
||||
debugSerial<<F("1-wire shorted.")<<endl;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
Serial.println(F("Searching"));
|
||||
if (oneWire) oneWire->reset_search();
|
||||
for (short i = 0; i < t_count; i++) wstat[i] &= ~SW_FIND; //absent
|
||||
@@ -78,6 +82,7 @@ int owUpdate() {
|
||||
|
||||
debugSerial<<F("1-wire count: ")<<t_count<<endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +124,12 @@ int owSetup(owChangedType owCh) {
|
||||
if (oneWire->wireReset())
|
||||
debugSerial.println(F("\tReset done"));
|
||||
|
||||
if (oneWire->getError() == DS2482_ERROR_SHORT)
|
||||
{
|
||||
debugSerial<<F("1-wire shorted.")<<endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
sensors->begin();
|
||||
owChanged = owCh;
|
||||
//owUpdate();
|
||||
@@ -141,7 +152,13 @@ int owSetup(owChangedType owCh) {
|
||||
|
||||
|
||||
int sensors_loop(void) {
|
||||
if (!sensors) return -1;
|
||||
if (!sensors) return 100000;
|
||||
if (oneWire->getError() == DS2482_ERROR_SHORT)
|
||||
{
|
||||
debugSerial<<F("1-wire disabled (shorted)")<<endl;
|
||||
return 100000;
|
||||
}
|
||||
|
||||
if (si >= t_count) {
|
||||
owUpdate(); //every check circle - scan for new devices
|
||||
si = 0;
|
||||
|
||||
@@ -67,6 +67,8 @@ const char SET_P[] PROGMEM = "set";
|
||||
const char CMD_P[] PROGMEM = "cmd";
|
||||
const char MODE_P[] PROGMEM = "mode";
|
||||
const char FAN_P[] PROGMEM = "fan";
|
||||
const char HUE_P[] PROGMEM = "hue";
|
||||
const char SAT_P[] PROGMEM = "sat";
|
||||
/*
|
||||
const char TEMP_P[] PROGMEM = "temp";
|
||||
const char SETPOINT_P[] PROGMEM = "setpoint";
|
||||
@@ -76,6 +78,7 @@ const char HEAT_P[] PROGMEM = "heat";
|
||||
*/
|
||||
const char HSV_P[] PROGMEM = "HSV";
|
||||
const char RGB_P[] PROGMEM = "RGB";
|
||||
|
||||
/*
|
||||
const char RPM_P[] PROGMEM = "rpm";
|
||||
const char STATE_P[] PROGMEM = "state";
|
||||
|
||||
+11
-3
@@ -21,7 +21,7 @@ e-mail anklimov@gmail.com
|
||||
#include "utils.h"
|
||||
#include "options.h"
|
||||
#include "stdarg.h"
|
||||
#include <wire.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#if defined(__SAM3X8E__) || defined(ARDUINO_ARCH_STM32)
|
||||
#include <malloc.h>
|
||||
@@ -396,11 +396,11 @@ if (topics && topics->type == aJson_Object)
|
||||
|
||||
|
||||
}
|
||||
if (_root) strncpy(buf,_root->valuestring,buflen);
|
||||
if (_root && _root->type == aJson_String) strncpy(buf,_root->valuestring,buflen);
|
||||
else strncpy_P(buf,homeTopic,buflen);
|
||||
strncat(buf,"/",buflen);
|
||||
|
||||
if (_l2) strncat(buf,_l2->valuestring,buflen);
|
||||
if (_l2 && _l2->type == aJson_String) strncat(buf,_l2->valuestring,buflen);
|
||||
else
|
||||
switch (tt) {
|
||||
case T_DEV:
|
||||
@@ -504,5 +504,13 @@ RebootFunc();
|
||||
#endif
|
||||
|
||||
|
||||
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo)
|
||||
{
|
||||
uint32_t endTime=(timestamp + time) % modulo;
|
||||
return ((currTime>endTime) && (currTime <timestamp)) ||
|
||||
((timestamp<endTime) && ((currTime>endTime) || (currTime <timestamp)));
|
||||
}
|
||||
|
||||
|
||||
#pragma message(VAR_NAME_VALUE(debugSerial))
|
||||
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
||||
|
||||
@@ -59,3 +59,4 @@ char* setTopic(char* buf, int8_t buflen, topicType tt, const char* suffix = NULL
|
||||
void printUlongValueToStr(char *valstr, unsigned long value);
|
||||
void scan_i2c_bus();
|
||||
void softRebootFunc();
|
||||
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo = 0xFFFFFFFF);
|
||||
|
||||
+60
-20
@@ -86,6 +86,8 @@ lib_ignore =
|
||||
SparkFun CCS811 Arduino Library
|
||||
ESP8266HTTPClient
|
||||
M5Stack
|
||||
;ArduinoOTA
|
||||
|
||||
lib_deps =
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
https://github.com/anklimov/DS2482_OneWire
|
||||
@@ -96,11 +98,13 @@ lib_deps =
|
||||
https://github.com/anklimov/ModbusMaster
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
; https://github.com/anklimov/Artnet.git
|
||||
; FastLED
|
||||
; FastLED@3.3.2
|
||||
Adafruit Unified Sensor
|
||||
DHT sensor library
|
||||
Streaming
|
||||
https://github.com/anklimov/NRFFlashStorage
|
||||
https://github.com/adafruit/Adafruit_NeoPixel.git
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
; https://github.com/livello/PrintEx#is-select-redecl
|
||||
|
||||
|
||||
@@ -145,11 +149,13 @@ lib_deps =
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
https://github.com/anklimov/DS2482_OneWire
|
||||
https://github.com/anklimov/ESP-Dmx
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
ClosedCube HDC1080
|
||||
;SparkFun CCS811 Arduino Library
|
||||
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library.git
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
M5Stack
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:esp32-wifi]
|
||||
platform = espressif32
|
||||
@@ -193,10 +199,13 @@ lib_deps =
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
https://github.com/anklimov/DS2482_OneWire
|
||||
https://github.com/anklimov/ESP-Dmx
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
ClosedCube HDC1080
|
||||
;SparkFun CCS811 Arduino Library
|
||||
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library.git
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:due-5100]
|
||||
platform = atmelsam
|
||||
framework = arduino
|
||||
@@ -217,6 +226,7 @@ lib_ignore =
|
||||
UIPEthernet
|
||||
EEPROM
|
||||
M5Stack
|
||||
;ArduinoOTA
|
||||
lib_deps =
|
||||
https://github.com/sebnil/DueFlashStorage
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
@@ -229,7 +239,7 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
SD
|
||||
SdFat
|
||||
Adafruit Unified Sensor
|
||||
@@ -237,7 +247,9 @@ lib_deps =
|
||||
https://github.com/arcao/Syslog.git
|
||||
Streaming
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:mega2560slim-5100]
|
||||
platform = atmelavr
|
||||
@@ -269,14 +281,16 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
;EEPROM
|
||||
Adafruit Unified Sensor
|
||||
DHT sensor library
|
||||
https://github.com/arcao/Syslog.git
|
||||
Streaming
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:mega2560-5500]
|
||||
platform = atmelavr
|
||||
@@ -308,19 +322,29 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet2
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
Adafruit Unified Sensor
|
||||
DHT sensor library
|
||||
https://github.com/arcao/Syslog.git
|
||||
Streaming
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
|
||||
[env:esp8266-wifi]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = nodemcuv2
|
||||
upload_protocol = esptool
|
||||
|
||||
;upload_protocol = espota
|
||||
;upload_port = Lighthub.local
|
||||
|
||||
;upload_flags =
|
||||
; --auth=password
|
||||
; --port=65280
|
||||
build_flags = !python get_build_flags.py esp8266-wifi
|
||||
lib_ignore =
|
||||
DmxSimple
|
||||
@@ -360,7 +384,11 @@ lib_deps =
|
||||
Streaming
|
||||
ESP_EEPROM
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA.git
|
||||
|
||||
|
||||
|
||||
[env:mega2560-5100]
|
||||
platform = atmelavr
|
||||
@@ -394,13 +422,15 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
Adafruit Unified Sensor
|
||||
DHT sensor library
|
||||
https://github.com/arcao/Syslog.git
|
||||
Streaming
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:due-5500]
|
||||
platform = atmelsam
|
||||
@@ -424,6 +454,7 @@ lib_ignore =
|
||||
ESP_EEPROM
|
||||
EEPROM
|
||||
M5Stack
|
||||
;ArduinoOTA
|
||||
lib_deps =
|
||||
https://github.com/sebnil/DueFlashStorage
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
@@ -436,7 +467,7 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet2
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
SD
|
||||
SdFat
|
||||
Adafruit Unified Sensor
|
||||
@@ -445,7 +476,9 @@ lib_deps =
|
||||
Streaming
|
||||
https://github.com/livello/PrintEx#is-select-redecl
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:lighthub21]
|
||||
platform = atmelsam
|
||||
@@ -468,6 +501,7 @@ lib_ignore =
|
||||
ESP_EEPROM
|
||||
EEPROM
|
||||
M5Stack
|
||||
;ArduinoOTA
|
||||
lib_deps =
|
||||
https://github.com/sebnil/DueFlashStorage
|
||||
https://github.com/anklimov/Arduino-Temperature-Control-Library.git
|
||||
@@ -480,7 +514,7 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet2
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
SD
|
||||
SdFat
|
||||
Adafruit Unified Sensor
|
||||
@@ -489,7 +523,9 @@ lib_deps =
|
||||
Streaming
|
||||
https://github.com/livello/PrintEx#is-select-redecl
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
|
||||
[env:controllino]
|
||||
@@ -523,14 +559,16 @@ lib_deps =
|
||||
https://github.com/anklimov/Ethernet
|
||||
https://github.com/knolleary/pubsubclient.git
|
||||
https://github.com/anklimov/Artnet.git
|
||||
FastLED
|
||||
FastLED@3.3.2
|
||||
;EEPROM
|
||||
Adafruit Unified Sensor
|
||||
DHT sensor library
|
||||
Streaming
|
||||
https://github.com/livello/PrintEx#is-select-redecl
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
SparkFun CCS811 Arduino Library@~1.0.7
|
||||
Adafruit NeoPixel
|
||||
https://github.com/anklimov/ArduinoOTA
|
||||
|
||||
[env:stm32-enc2860]
|
||||
platform = ststm32
|
||||
@@ -568,6 +606,7 @@ lib_ignore =
|
||||
ClosedCube HDC1080
|
||||
SparkFun CCS811 Arduino Library
|
||||
M5Stack
|
||||
ArduinoOTA
|
||||
lib_deps =
|
||||
https://github.com/anklimov/aJson
|
||||
https://github.com/anklimov/CmdArduino
|
||||
@@ -576,3 +615,4 @@ lib_deps =
|
||||
Streaming
|
||||
UIPEthernet
|
||||
https://github.com/anklimov/NRFFlashStorage
|
||||
Adafruit NeoPixel
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user