mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03: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
|
||||
|
||||
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.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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;
|
||||
};
|
||||
|
||||
23
lighthub/bright.cpp
Normal file
23
lighthub/bright.cpp
Normal file
@@ -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
|
||||
}
|
||||
105
lighthub/bright.h
Normal file
105
lighthub/bright.h
Normal file
@@ -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);
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
284
lighthub/modules/out_motor.cpp
Normal file
284
lighthub/modules/out_motor.cpp
Normal file
@@ -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
|
||||
39
lighthub/modules/out_motor.h
Normal file
39
lighthub/modules/out_motor.h
Normal file
@@ -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
|
||||
@@ -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);
|
||||
};
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
7663
spare_files/flows (4).json
Normal file
7663
spare_files/flows (4).json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user