diff --git a/compiled/DUE_16u2_reflash/16u2.hex b/compiled/DUE_16u2_reflash/16u2.hex new file mode 100644 index 0000000..33363e7 --- /dev/null +++ b/compiled/DUE_16u2_reflash/16u2.hex @@ -0,0 +1,273 @@ +:10000000A7C00000C0C00000BEC00000BCC000000F +:10001000BAC00000B8C00000B6C00000B4C0000004 +:10002000B2C00000B0C00000AEC00000C1C40000FB +:1000300085C40000A8C00000A6C00000A4C0000045 +:10004000A2C00000A0C000009EC000009CC0000034 +:100050009AC0000098C0000096C0000021C10000B6 +:1000600092C0000090C000008EC000008CC0000054 +:100070008AC0000088C0000086C0000084C0000064 +:1000800082C0000080C000007EC000007CC0000074 +:100090007AC0000078C000001201100102000008C0 +:1000A00041233D0001000102DC0109023E00020182 +:1000B00000C0320904000001020201000524000111 +:1000C0001004240206052406000107058203080027 +:1000D000FF09040100020A000000070504024000B5 +:1000E00001070583024000010403090432034100B3 +:1000F00072006400750069006E006F002000280027 +:100100007700770077002E006100720064007500B0 +:1001100069006E006F002E0063006300290000007C +:100120002E03410072006400750069006E006F00CC +:1001300020004400750065002000500072006F0030 +:1001400067002E00200050006F0072007400000055 +:1001500011241FBECFEFD2E0DEBFCDBF11E0A0E083 +:10016000B1E0E4EDF0E102C005900D92A831B107D5 +:10017000D9F712E0A8E1B1E001C01D92A833B107A0 +:10018000E1F72BD1A5C73CCF9C01DC01AE57BF4F97 +:10019000ED91FC91119741911196FC93EE9380584B +:1001A0009F4FE817F90711F42D933C939FB7F894EC +:1001B000F901EC57FF4F8081815080839FBF842FCE +:1001C0000895882311F03F9A01C03F9847980895F9 +:1001D000882311F046980895469A0895DF92EF9289 +:1001E000FF920F931F93FC018489813019F08230B4 +:1001F00019F404C010E303C010E001C010E28389C9 +:10020000823009F418608589873031F0883031F008 +:10021000863029F4126003C0146001C01660109289 +:10022000C9001092C8001092CA000785F088E188C2 +:10023000D288202F3F2D4E2D5D2D10921E01203B88 +:1002400084E0380780E0480780E0580719F481E02F +:1002500080931E01CA01B90122E030E040E050E085 +:100260001CD720583B47414E5F4FCA01B901202F90 +:100270003F2D4E2D5D2DEFD6215030403093CD00D7 +:100280002093CC001093CA0082E08093C80088E9D4 +:100290008093C9001F910F91FF90EF90DF90089518 +:1002A0001F920F920FB60F9211242F938F939F934B +:1002B000EF93FF939091CE008EB38430F1F4E091F0 +:1002C000A201F091A3019083E091A201F091A3011A +:1002D000CF0101969093A3018093A201825A91408D +:1002E00021F482E291E0928381839FB7F894809118 +:1002F000A6018F5F8093A6019FBFFF91EF919F9111 +:100300008F912F910F900FBE0F901F901895FC01A9 +:1003100040911A0140931B0180911C0180931D01A3 +:100320008585282F30E02170307020931A01858553 +:1003300090E096958795817080931C0180911E01B5 +:10034000882339F088E790E0909319018093180191 +:100350000895442341F4222331F082E390E0909306 +:10036000190180931801089580E091E00AC680E0A9 +:1003700091E0BDC584B7877F84BF88E10FB6F8944C +:1003800080936000109260000FBE81E01ADF16BCFF +:1003900083E085BD86B58831E8F315BC16BC80E0E6 +:1003A00010DF469A3E9A87E690E09093CD008093C6 +:1003B000CC0086E08093CA001092C80088E1809348 +:1003C000C900539A5A9A8AB180638AB98BB1806303 +:1003D0008BB9A9D284E085BD08950F931F93CF9365 +:1003E000DF93C8DF2FB7F89487EA91E09093280253 +:1003F0008093270290932A02809329022FBF2FB760 +:10040000F89482E291E09093A3018093A2019093EB +:10041000A5018093A4012FBF7894C7EAD1E003E03F +:100420008FB7F89490912B028FBF903809F180E03C +:1004300091E0D3D497FD1CC0E0912702F0912802EF +:100440008083E0912702F0912802CF0101969093DA +:100450002802809327028752924011F4D283C183ED +:100460009FB7F89480912B028F5F80932B029FBFE0 +:100470008FB7F8941091A6018FBFA89903C01136C9 +:1004800008F456C0A89A8091A601882361F05D986F +:1004900000931F0108C082E291E076DE682F80E0C1 +:1004A00091E001D511501123B1F780911F018823EC +:1004B00051F080911F01815080931F0180911F0195 +:1004C000882309F45D9A80912001882351F080915E +:1004D000200181508093200180912001882309F41C +:1004E0005C9A809118019091190118161906E4F48C +:1004F000CC97CD9710F481E001C080E069DE809157 +:100500001801909119010197C29710F481E001C080 +:1005100080E057DE80911801909119010197909326 +:1005200019018093180104C080E052DE80E049DEAA +:100530008FB7F89490912B028FBF992369F087EAC7 +:1005400091E022DE982F8091C80085FFFCCF909328 +:10055000CE005C980093200180E091E095D42AD4ED +:100560005FCFDA01923049F0933061F09130F9F4C5 +:10057000E8E9F0E022E130E01EC0EAEAF0E02EE334 +:1005800030E019C0813049F0813018F0823079F4C0 +:1005900008C0E8EEF0E0849107C0ECEEF0E0849152 +:1005A00003C0E0E2F1E08491282F30E004C0E0E0F5 +:1005B000F0E020E030E0ED93FC93C901089528E0DD +:1005C00030E040E003C04F5F220F331F2817390788 +:1005D000D0F3842F8295807F08958093E9008091E5 +:1005E000EB0081608093EB001092ED006093EC00D3 +:1005F0004093ED008091EE00881F8827881F0895A2 +:100600001092F40090E09093E9001092F0001092A4 +:10061000E8001092ED008091EB008E7F8093EB005C +:100620009F5F953081F708958091300288238CF484 +:1006300003C08EB38823B1F08091E80082FFF9CF28 +:100640008091E8008B778093E80008958EB388232B +:1006500049F08091E80080FFF9CF8091E8008E7723 +:100660008093E800089594E68091EC0080FF05C037 +:100670008091E80080FF05C023C08091E80082FDE2 +:100680001FC08EB3882311F482E008958EB38530A5 +:1006900011F483E008958091EB0085FF02C081E0B2 +:1006A00008958091E10082FFDFCF8091E1008B7F90 +:1006B0008093E100992311F484E008959150D4CF00 +:1006C00080E008959C014091360250913702461710 +:1006D000570718F4F90120E038C06115710511F0D1 +:1006E000AB01F8CF8091E8008E778093E80040E07E +:1006F00050E0F0CF8091E80083FF02C081E00895D0 +:100700008091E80082FD2DC08EB3882381F18EB3E5 +:10071000853079F18091E80080FF17C09091F20058 +:1007200006C081918093F100415050409F5F411578 +:10073000510511F09830A8F320E0983009F421E039 +:100740008091E8008E778093E8004115510591F67D +:10075000222381F606C08EB3882349F08EB38530FC +:1007600041F08091E80082FFF6CF80E0089582E0BA +:10077000089583E008959C0140913602509137021C +:100780004617570710F490E03BC06115710511F052 +:10079000AB01F9CF8091E8008E778093E80040E0CC +:1007A00050E0F1CF8091E80083FF02C081E008951E +:1007B0008091E80082FD30C08EB3882399F18EB31A +:1007C000853091F18091E80080FF1AC08091F2009D +:1007D00009C0F9012F5F3F4FE491E093F1004150D0 +:1007E00050408F5F4115510511F0883090F390E033 +:1007F000883009F491E08091E8008E778093E800DA +:100800004115510579F6992369F606C08EB3882300 +:1008100049F08EB3853041F08091E80082FFF6CF39 +:1008200080E0089582E0089583E008959C016115B9 +:10083000710529F48091E8008B778093E800F90135 +:1008400020C08091E80083FF02C081E008958EB34C +:10085000882339F18EB3853031F18091E80082FF31 +:10086000F0CF06C08091F10081936150704021F07B +:100870008091F2008823B1F78091E8008B77809314 +:10088000E80061157105E9F606C08EB3882349F0CA +:100890008EB3853041F08091E80080FFF6CF80E094 +:1008A000089582E0089583E0089542D044D01EBAAE +:1008B00010922E0210922D0210922C0284E089BD1B +:1008C00089B5826089BD09B400FEFDCF8091D80052 +:1008D000982F9F779093D80080688093D80080915C +:1008E00063008E7F809363008091D8008F7D80931A +:1008F000D8008091E0008E7F8093E0008091E1003D +:100900008E7F8093E1008091E20081608093E2001D +:100910008091E100877F8093E1008091E200886010 +:100920008093E2000895C1DF81E080932F02089553 +:100930001092E20008951092E10008951F920F9224 +:100940000FB60F9211241F932F933F934F935F93F2 +:100950006F937F938F939F93AF93BF93EF93FF9387 +:10096000E9EEF0E0108117701082E0EFF0E0808196 +:10097000877F80837894C3D0F894A9EEB0E01C926E +:10098000E0EFF0E08081886080831C93FF91EF911D +:10099000BF91AF919F918F917F916F915F914F9197 +:1009A0003F912F911F910F900FBE0F901F901895A0 +:1009B0001F920F920FB60F9211242F933F934F93D4 +:1009C0005F936F937F938F939F93AF93BF93EF93B7 +:1009D000FF938091E10080FF1BC08091E20080FFC7 +:1009E00017C08091E1008E7F8093E1008091E2004A +:1009F0008E7F8093E2008091E20080618093E2002C +:100A00008091D80080628093D80019BC1EBAD1D1E1 +:100A10008091E10084FF29C08091E20084FF25C01D +:100A200084E089BD89B5826089BD09B400FEFDCF2F +:100A30008091D8008F7D8093D8008091E1008F7ED7 +:100A40008093E1008091E2008F7E8093E2008091AC +:100A5000E20081608093E20080912E02882311F4ED +:100A600081E001C084E08EBBA4D18091E10083FFCE +:100A700027C08091E20083FF23C08091E100877F3F +:100A80008093E10082E08EBB10922E028091E10003 +:100A90008E7F8093E1008091E2008E7F8093E20060 +:100AA0008091E20080618093E200AADD80E060E056 +:100AB00042E093DD8091F00088608093F00079D16E +:100AC0008091E10082FF0AC08091E20082FF06C0AF +:100AD0008091E1008B7F8093E1006BD1FF91EF91DA +:100AE000BF91AF919F918F917F916F915F914F9146 +:100AF0003F912F910F900FBE0F901F9018951F934D +:100B0000DF93CF93CDB7DEB7AC970FB6F894DEBFC7 +:100B10000FBECDBFE0E3F2E08091F100819322E0CF +:100B2000E833F207C9F78091300230913102353055 +:100B300009F487C0363040F43130C9F1313070F0FB +:100B4000333009F01DC133C0383009F4EFC03930FB +:100B500009F4FEC0363009F013C192C0803821F08C +:100B6000823809F00DC108C090912C0280912D02AD +:100B7000882399F0926011C080913402877080932D +:100B8000E9008091EB0090E025E0969587952A9505 +:100B9000E1F7982F91701092E9008091E800877F2B +:100BA0008093E8009093F1001092F100CAC088236E +:100BB00019F0823009F0E4C090E08F7190700097D6 +:100BC00021F0029709F0DDC00CC080913202813023 +:100BD00009F0D7C010922D02333069F580932D02B1 +:100BE0002AC080913202882331F520913402277087 +:100BF00009F4C7C02093E9008091EB0080FFC1C0D9 +:100C0000333021F48091EB00806213C08091EB00BF +:100C100080618093EB0081E090E002C0880F991F13 +:100C20002A95E2F78093EA001092EA008091EB00A7 +:100C300088608093EB001092E9008091E800877F44 +:100C400083C0882309F09CC0109132028091E80093 +:100C5000877F8093E800E8DC04C08EB3882309F422 +:100C600090C08091E80080FFF8CF812F8F7711F43A +:100C700092E001C093E09EBB80688093E30081C056 +:100C80008058823008F07CC080913202909133020B +:100C900023E08C3D920799F55FB7F894DE01159635 +:100CA0004EE020E030E061E2E42FF0E06093570096 +:100CB000849120FF03C082958F704F5F982F9F70A3 +:100CC000892F805D8A3308F0895F8C9311961C927E +:100CD00011972F5F3F4F12962431310529F75FBFDF +:100CE0008AE28B8383E08C838091E800877F809306 +:100CF000E800CE0103966AE270E0E4DC11C0609186 +:100D00003402AE014F5F5F4F2CDCBC010097C9F18C +:100D10008091E800877F8093E80089819A812BDDAC +:100D20008091E8008B778093E8002BC0803841F5F4 +:100D30008091E800877F8093E80080912E02809365 +:100D4000F1008091E8008E778093E8006DDC19C097 +:100D50008823B1F490913202923098F48091E800A7 +:100D6000877F8093E80090932E025EDC80912E02B4 +:100D7000882311F483E001C084E08EBBF8DA01C05F +:100D8000F3DA8091E80083FF0AC08091EB00806273 +:100D90008093EB008091E800877F8093E800AC9619 +:100DA0000FB6F894DEBF0FBECDBFCF91DF911F917C +:100DB000089508951F938EB3882361F01091E90080 +:100DC0001092E9008091E80083FF01C098DE17705F +:100DD0001093E9001F9108950895FC018EB38430AB +:100DE00021F587859089A189B2890097A105B10570 +:100DF000E1F085818093E9008091E80082FF15C0D1 +:100E00008091F200882319F42FEF3FEF04C0809106 +:100E1000F100282F30E08091F200882341F4809186 +:100E2000E8008B778093E80002C02FEF3FEFC90105 +:100E30000895FC018EB3843011F587859089A189CE +:100E4000B2890097A105B105D1F081818093E900B5 +:100E50008091F2008823A9F09091E8008091E80049 +:100E60008E778093E80095FD0CC0FDDB982F8823DA +:100E700049F48091E8008E778093E80003C092E007 +:100E800001C090E0892F0895FC018EB3843051F4A5 +:100E900087859089A189B2890097A105B10511F0D4 +:100EA000CF01C7CF08951F93FC01162F8EB3843056 +:100EB000D9F487859089A189B2890097A105B105E8 +:100EC00099F081818093E9008091E80085FD08C058 +:100ED0008091E8008E778093E800C5DB882329F4B1 +:100EE0001093F10080E001C082E01F9108950F93FC +:100EF0001F93CF93DF93EC010D96FC0189E0DF0196 +:100F00001D928A95E9F72A813B8109818C8188238A +:100F100011F410E001C014E0C90151DB182B12607C +:100F2000802F61E8412F59DB882329F12E813F81F1 +:100F30000D818885882311F410E001C014E0C901F7 +:100F40003EDB182B1260802F60E8412F46DB8823A0 +:100F500091F02A853B8509858C85882311F410E062 +:100F600001C014E0C9012BDB182B1260802F61EC4B +:100F7000412F33DB01C080E0DF91CF911F910F91B2 +:100F80000895CF93DF93EC018091E80083FF60C068 +:100F9000888190E02091340230913502281739077A +:100FA00009F056C080913102813261F0823220F422 +:100FB000803209F04DC019C0823269F1833209F0E4 +:100FC00047C038C080913002813A09F041C0809119 +:100FD000E800877F8093E800CE010F9667E070E01D +:100FE00071DB8091E8008B7713C0809130028132F1 +:100FF00079F58091E800877F8093E800CE010F9615 +:1010000067E070E013DCCE01E9D88091E8008E77CC +:101010008093E8001DC0809130028132C9F4809134 +:10102000E800877F8093E800809132028D87CE01AF +:101030006ED90DC080913002813251F48091E80068 +:10104000877F8093E800CE0160913202C5DEECDA42 +:10105000DF91CF910895A1E21A2EAA1BBB1BFD01BF +:101060000DC0AA1FBB1FEE1FFF1FA217B307E40787 +:10107000F50720F0A21BB30BE40BF50B661F771FDF +:10108000881F991F1A9469F76095709580959095BF +:101090009B01AC01BD01CF01089597FB092E0526E8 +:1010A0000ED057FD04D0D7DF0AD0001C38F450957D +:1010B0004095309521953F4F4F4F5F4F0895F6F77C +:1010C00090958095709561957F4F8F4F9F4F0895B4 +:0410D000F894FFCFC2 +:1010D400000340000004400000020800000000007B +:0810E4000000000000001400F0 +:00000001FF diff --git a/compiled/DUE_16u2_reflash/reflash16u2DUE.sh b/compiled/DUE_16u2_reflash/reflash16u2DUE.sh old mode 100644 new mode 100755 diff --git a/compiled/due-5500/firmware.bin b/compiled/due-5500/firmware.bin index d001e0e..8cd10fd 100644 Binary files a/compiled/due-5500/firmware.bin and b/compiled/due-5500/firmware.bin differ diff --git a/lighthub/abstractch.cpp b/lighthub/abstractch.cpp new file mode 100644 index 0000000..48f3bf8 --- /dev/null +++ b/lighthub/abstractch.cpp @@ -0,0 +1,41 @@ + +#include "abstractch.h" +#include +#include "utils.h" +#include +#include "main.h" + +extern lan_status lanStatus; +extern PubSubClient mqttClient; + +int abstractCh::publishTopic(const char* topic, long value, const char* subtopic) +{ + char valstr[16]; + printUlongValueToStr(valstr, value); + return publishTopic(topic, valstr,subtopic); +}; + +int abstractCh::publishTopic(const char* topic, float value, const char* subtopic) +{ + char valstr[16]; + printFloatValueToStr(value, valstr); + return publishTopic(topic, valstr,subtopic); +}; + +int abstractCh::publishTopic(const char* topic, const char * value, const char* subtopic) +{ + char addrstr[MQTT_TOPIC_LENGTH]; + + if (topic) + { + 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) + { + mqttClient.publish(addrstr, value, true); + return 1; + } + } + +}; diff --git a/lighthub/abstractch.h b/lighthub/abstractch.h new file mode 100644 index 0000000..6c923ed --- /dev/null +++ b/lighthub/abstractch.h @@ -0,0 +1,23 @@ +#pragma once +#include "Arduino.h" + +#define CST_UNKNOWN 0 +#define CST_INITIALIZED 1 + +class abstractCh { +public: + abstractCh(){}; + virtual ~abstractCh(){}; + virtual int Poll() = 0; + virtual int Setup() =0; //Should initialize hardware and reserve resources + virtual int Anounce () {return 0;}; + virtual int Stop() {return 0;}; //Should free resources + virtual int Status() {return CST_UNKNOWN;} + + +protected: +virtual int publishTopic(const char* topic, long value, const char* subtopic = NULL); +virtual int publishTopic(const char* topic, float value, const char* subtopic = NULL ); +virtual int publishTopic(const char* topic, const char * value, const char* subtopic = NULL); +//friend Input; +}; diff --git a/lighthub/abstractin.cpp b/lighthub/abstractin.cpp index 2461f55..8956bbb 100644 --- a/lighthub/abstractin.cpp +++ b/lighthub/abstractin.cpp @@ -1,5 +1,6 @@ #include "abstractin.h" +#include "abstractch.h" #include #include "utils.h" #include @@ -9,21 +10,21 @@ extern lan_status lanStatus; extern PubSubClient mqttClient; -int abstractIn::publish(long value, char* subtopic) +int abstractIn::publish(long value, const char* subtopic) { char valstr[16]; printUlongValueToStr(valstr, value); return publish(valstr,subtopic); }; -int abstractIn::publish(float value, char* subtopic) +int abstractIn::publish(float value, const char* subtopic) { char valstr[16]; printFloatValueToStr(value, valstr); return publish(valstr,subtopic); }; -int abstractIn::publish(char * value, char* subtopic) +int abstractIn::publish(char * value, const char* subtopic) { char addrstr[MQTT_TOPIC_LENGTH]; if (in) @@ -31,14 +32,7 @@ int abstractIn::publish(char * value, char* subtopic) aJsonObject *emit = aJson.getObjectItem(in->inputObj, "emit"); if (emit) { - strncpy(addrstr,emit->valuestring,sizeof(addrstr)); - if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); - strncat(addrstr,subtopic,sizeof(addrstr)); - if (mqttClient.connected() && lanStatus == OPERATION) - { - mqttClient.publish(addrstr, value, true); - return 1; - } + return publishTopic(emit->valuestring,value,subtopic); } } return 0; diff --git a/lighthub/abstractin.h b/lighthub/abstractin.h index 5d2ca4e..87f3748 100644 --- a/lighthub/abstractin.h +++ b/lighthub/abstractin.h @@ -1,17 +1,16 @@ #pragma once #include "Arduino.h" +#include "abstractch.h" class Input; -class abstractIn { +class abstractIn : public abstractCh{ public: - abstractIn(Input * _in){in=_in;}; - virtual int Setup(int addr) = 0; - virtual int Poll() = 0; + abstractIn(Input * _in):abstractCh(){in=_in;}; protected: Input * in; -int publish(long value, char* subtopic = NULL); -int publish(float value, char* subtopic = NULL ); -int publish(char * value, char* subtopic = NULL); +int publish(long value, const char* subtopic = NULL); +int publish(float value, const char* subtopic = NULL ); +int publish(char * value, const char* subtopic = NULL); friend Input; }; diff --git a/lighthub/abstractout.h b/lighthub/abstractout.h new file mode 100644 index 0000000..766027d --- /dev/null +++ b/lighthub/abstractout.h @@ -0,0 +1,14 @@ +#pragma once +#include "Arduino.h" +#include "abstractch.h" + +class Item; +class abstractOut : public abstractCh{ +public: + abstractOut(Item * _item):abstractCh(){item=_item;}; + 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;}; +protected: + Item * item; +}; diff --git a/lighthub/inputs.cpp b/lighthub/inputs.cpp index 41f49a3..5626e56 100644 --- a/lighthub/inputs.cpp +++ b/lighthub/inputs.cpp @@ -118,12 +118,12 @@ if (!isValid() || (!root)) return; if (inType == IN_CCS811) { in_ccs811 ccs811(this); - ccs811.Setup(pin); + ccs811.Setup(); } else if (inType == IN_HDC1080) { in_hdc1080 hdc1080(this); - hdc1080.Setup(pin); + hdc1080.Setup(); } // TODO rest types setup #endif @@ -188,6 +188,7 @@ switch (cause) { #endif } } + return 0; } #ifndef COUNTER_DISABLE @@ -226,7 +227,7 @@ void Input::counterPoll() { char addrstr[MQTT_TOPIC_LENGTH]; strncpy(addrstr,emit->valuestring,sizeof(addrstr)); if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); - sprintf(valstr, "%d", counterValue); + sprintf(valstr, "%ld", counterValue); if (mqttClient.connected() && !ethernetIdleCount) mqttClient.publish(addrstr, valstr); setNextPollTime(millis() + DHT_POLL_DELAY_DEFAULT); @@ -435,13 +436,15 @@ void Input::contactPoll() { if (inType & IN_PUSH_TOGGLE) { if (currentInputState) { //react on leading edge only (change from 0 to 1) store->logicState = !store->logicState; + store->currentValue = currentInputState; onContactChanged(store->logicState); } } else { store->logicState = currentInputState; + store->currentValue = currentInputState; onContactChanged(currentInputState); } - store->currentValue = currentInputState; + // store->currentValue = currentInputState; } } else // no change store->bounce = SAME_STATE_ATTEMPTS; diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 0be0482..90bcef8 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -31,61 +31,77 @@ e-mail anklimov@gmail.com #ifndef MODBUS_DISABLE #include #endif -#include -const char ON_P[] PROGMEM = "ON"; -const char OFF_P[] PROGMEM = "OFF"; +#include +#include "modules/out_spiled.h" +#include "modules/out_ac.h" + +//Commands +const char ON_P[] PROGMEM = "ON"; +const char OFF_P[] PROGMEM = "OFF"; const char REST_P[] PROGMEM = "REST"; const char TOGGLE_P[] PROGMEM = "TOGGLE"; const char HALT_P[] PROGMEM = "HALT"; -const char XON_P[] PROGMEM = "XON"; +const char XON_P[] PROGMEM = "XON"; const char XOFF_P[] PROGMEM = "XOFF"; const char INCREASE_P[] PROGMEM = "INCREASE"; const char DECREASE_P[] PROGMEM = "DECREASE"; -const char TRUE_P[] PROGMEM = "true"; -const char FALSE_P[] PROGMEM = "false"; +const char TRUE_P[] PROGMEM = "TRUE"; +const char FALSE_P[] PROGMEM = "FALSE"; -const char SET_P[] PROGMEM = "set"; -const char TEMP_P[] PROGMEM = "temp"; +char HEAT_P[] PROGMEM = "HEAT"; +char COOL_P[] PROGMEM = "COOL"; +char AUTO_P[] PROGMEM = "AUTO"; +char FAN_ONLY_P[] PROGMEM = "FAN_ONLY"; +char DRY_P[] PROGMEM = "DRY"; + +// SubTopics +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 TEMP_P[] PROGMEM = "temp"; const char SETPOINT_P[] PROGMEM = "setpoint"; const char POWER_P[] PROGMEM = "power"; const char VOL_P[] PROGMEM = "vol"; 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 HSV_P[] PROGMEM = "hsv"; +const char RGB_P[] PROGMEM = "rgb"; +/* +const char RPM_P[] PROGMEM = "rpm"; +const char STATE_P[] PROGMEM = "state"; +*/ short modbusBusy = 0; extern aJsonObject *pollingItem; - - -//int modbusSet(int addr, uint16_t _reg, int _mask, uint16_t value); - extern PubSubClient mqttClient; extern int8_t ethernetIdleCount; -//extern char outprefix[]; -//const char outprefix[] PROGMEM = OUTTOPIC; static unsigned long lastctrl = 0; static aJsonObject *lastobj = NULL; int txt2cmd(char *payload) { - int cmd = -1; + int cmd = CMD_UNKNOWN; // Check for command - if (strcmp_P(payload, ON_P) == 0) cmd = CMD_ON; + if (*payload == '-' || (*payload >= '0' && *payload <= '9')) cmd = CMD_NUM; + else if (strcmp_P(payload, ON_P) == 0) cmd = CMD_ON; else if (strcmp_P(payload, OFF_P) == 0) cmd = CMD_OFF; else if (strcmp_P(payload, REST_P) == 0) cmd = CMD_RESTORE; else if (strcmp_P(payload, TOGGLE_P) == 0) cmd = CMD_TOGGLE; else if (strcmp_P(payload, HALT_P) == 0) cmd = CMD_HALT; else if (strcmp_P(payload, XON_P) == 0) cmd = CMD_XON; else if (strcmp_P(payload, XOFF_P) == 0) cmd = CMD_XOFF; + else if (strcmp_P(payload, HEAT_P) == 0) cmd = CMD_HEAT; + else if (strcmp_P(payload, COOL_P) == 0) cmd = CMD_COOL; + else if (strcmp_P(payload, AUTO_P) == 0) cmd = CMD_AUTO; + else if (strcmp_P(payload, FAN_ONLY_P) == 0) cmd = CMD_FAN; + else if (strcmp_P(payload, DRY_P) == 0) cmd = CMD_DRY; else if (strcmp_P(payload, TRUE_P) == 0) cmd = CMD_ON; else if (strcmp_P(payload, FALSE_P) == 0) cmd = CMD_OFF; else if (strcmp_P(payload, INCREASE_P) == 0) cmd = CMD_UP; else if (strcmp_P(payload, DECREASE_P) == 0) cmd = CMD_DN; - else if (*payload == '-' || (*payload >= '0' && *payload <= '9')) cmd = CMD_NUM; //0 else if (*payload == '{') cmd = CMD_JSON; else if (*payload == '#') cmd = CMD_RGB; else if (strncmp_P(payload, HSV_P, strlen (HSV_P)) == 0) cmd = CMD_HSV; @@ -95,18 +111,21 @@ int txt2cmd(char *payload) { int txt2subItem(char *payload) { - int cmd = -1; - if (!payload || !strlen(payload)) return 0; + int cmd = S_NOTFOUND; + if (!payload || !strlen(payload)) return S_NOTFOUND; // Check for command if (strcmp_P(payload, SET_P) == 0) cmd = S_SET; - else if (strcmp_P(payload, TEMP_P) == 0) cmd = S_TEMP; + else if (strcmp_P(payload, CMD_P) == 0) cmd = S_CMD; else if (strcmp_P(payload, MODE_P) == 0) cmd = S_MODE; - else if (strcmp_P(payload, SETPOINT_P) == 0) cmd = S_SETPOINT; - else if (strcmp_P(payload, POWER_P) == 0) cmd = S_POWER; - else if (strcmp_P(payload, VOL_P) == 0) cmd = S_VOL; - else if (strcmp_P(payload, HEAT_P) == 0) cmd = S_HEAT; else if (strcmp_P(payload, HSV_P) == 0) cmd = S_HSV; else if (strcmp_P(payload, RGB_P) == 0) cmd = S_RGB; + else if (strcmp_P(payload, FAN_P) == 0) cmd = S_FAN; + /* UnUsed now + else if (strcmp_P(payload, SETPOINT_P) == 0) cmd = S_SETPOINT; + else if (strcmp_P(payload, TEMP_P) == 0) cmd = S_TEMP; + else if (strcmp_P(payload, POWER_P) == 0) cmd = S_POWER; + else if (strcmp_P(payload, VOL_P) == 0) cmd = S_VOL; + */ return cmd; } @@ -115,6 +134,7 @@ const short defval[4] = {0, 0, 0, 0}; //Type,Arg,Val,Cmd Item::Item(aJsonObject *obj)//Constructor { itemArr = obj; + driver = NULL; Parse(); } @@ -127,24 +147,63 @@ void Item::Parse() { itemType = aJson.getArrayItem(itemArr, I_TYPE)->valueint; itemArg = aJson.getArrayItem(itemArr, I_ARG); itemVal = aJson.getArrayItem(itemArr, I_VAL); + + switch (itemType) + { +#ifndef SPILED_DISABLE + case CH_SPILED: + driver = new out_SPILed (this); + debugSerial<name << F(" T:") << itemType << F(" =") << getArg() << endl; + } } + +boolean Item::Setup() +{ + +if (driver) + { + if (driver->Status()) driver->Stop(); + driver->Setup(); + return true; + } +else return false; +} + +Item::~Item() +{ + if (driver) + { + delete driver; + debugSerial<valueint; - else return t->valueint & CMD_MASK; + return t->valueint & CMD_MASK; else return -1; } @@ -153,11 +212,42 @@ void Item::setCmd(uint8_t cmdValue) { aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD); if (itemCmd) { - itemCmd->valueint = cmdValue; + itemCmd->valueint = cmdValue & CMD_MASK | itemCmd->valueint & FLAG_MASK; // Preserve special bits debugSerial<valueint & flag & FLAG_MASK; + } +} + +void Item::setFlag (short flag) +{ + aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD); + if (itemCmd) + { + itemCmd->valueint |= flag & FLAG_MASK; // Preserve CMD bits + debugSerial<valueint &= CMD_MASK | ~(flag & FLAG_MASK); // Preserve CMD bits + debugSerial< (unsigned long) delta));// || ((void *)itemArr != (void *) lastobj)); } +*/ #define MAXCTRLPAR 3 - +// myhome/dev/item/subItem int Item::Ctrl(char * payload, boolean send, char * subItem){ if (!payload) return 0; -char* subsubItem = NULL; -int subItemN = 0; -int subsubItemN = 0; -bool isSet = false; +char* suffix = NULL; +int suffixCode = 0; +int setCommand = CMD_SET; //default SET behavior now - not turn on channels if (subItem && strlen(subItem)) { -if (subsubItem = strchr(subItem, '/')) +if (suffix = strrchr(subItem, '/')) //Trying to retrieving right part { - *subsubItem = 0; - subsubItem++; - subsubItemN = txt2subItem(subsubItem); + *suffix= 0; //Truncate subItem string + suffix++; + suffixCode = txt2subItem(suffix); + // myhome/dev/item/sub.....Item/suffix } - subItemN = txt2subItem(subItem); - if (subItemN==S_SET || subsubItemN==S_SET) isSet = true; -} else isSet = true; /// To be removed - old compatmode +else + { + suffix = subItem; + suffixCode = txt2subItem(suffix); + if (suffixCode) // some known suffix + subItem = NULL; + // myhome/dev/item/suffix -if (isSet) + else //Invalid suffix - fallback to Subitem notation + suffix = NULL; + // myhome/dev/item/subItem + } +} else { - int cmd = txt2cmd(payload); - debugSerial< "); + debugSerial<"); } - debugSerial<0) cmd = CMD_OFF; else cmd = CMD_ON; break; @@ -354,61 +480,89 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send, int subItemN) default: debugSerial<Ctrl(cmd, n, Parameters, send, suffixCode, subItem); + // Legacy code + bool toExecute = (chActive>0); //if channel is already active - unconditionally propogate changes switch (cmd) { - case 0: //no command + case 0: // old style SET - with turning ON + toExecute = true; + case CMD_SET: // new style SET - w/o turning ON - if (itemType !=CH_THERMO) setCmd(CMD_SET); //prevent ON thermostat by semp set + //if (/*itemType !=CH_THERMO && */send) setCmd(CMD_SET); //prevent ON thermostat by semp set ???? switch (itemType) { case CH_RGBW: //only if configured VAL array if (!Par[1] && (n == 3)) itemType = CH_WHITE; case CH_RGB: - if (n == 3) { // Full triplet passed - st.h = Par[0]; - st.s = Par[1]; - st.v = Par[2]; - setVal(st.aslong); - } else // Just volume passed - { - st.aslong = getVal(); // restore Colour - st.v = Par[0]; // override volume - setVal(st.aslong); // Save back - Par[0] = st.h; - Par[1] = st.s; - Par[2] = st.v; - n = 3; - } - if (send) SendStatus(0,3,Par,true); // Send back triplet ? - break; case CH_GROUP: //Save for groups as well - st.h = Par[0]; - st.s = Par[1]; - st.v = Par[2]; - setVal(st.aslong); + st.aslong = getVal(); + switch (n) + { + case 1: + + st.v = Par[0]; //Volume only + if (st.hsv_flag) + { + Par[0] = st.h; + Par[1] = st.s; + Par[2] = st.v; + n = 3;} + break; + case 2: // Just hue and saturation + st.h = Par[0]; + st.s = Par[1]; + Par[2] = st.v; + st.hsv_flag = 1; + n = 3; + break; + case 3: //complete triplet + st.h = Par[0]; + st.s = Par[1]; + st.v = Par[2]; + st.hsv_flag = 1; + } + setVal(st.aslong); + if (toExecute) + { // + if (chActive && !st.v) setCmd(CMD_OFF); + if (!chActive && st.v) setCmd(CMD_ON); + SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED); + } + else SendStatus(SEND_PARAMETERS | SEND_DEFFERED); break; case CH_PWM: case CH_VC: case CH_DIMMER: case CH_MODBUS: - case CH_VCTEMP: - if (send) SendStatus(0, 1, Par,true); // Send back parameter for channel above this line - case CH_THERMO: setVal(Par[0]); // Store value +// setCmd(cmd2changeActivity(chActive,cmd)); + if (toExecute) + { // Not restoring, working + if (chActive && !Par[0]) setCmd(CMD_OFF); + if (!chActive && Par[0]) setCmd(CMD_ON); + SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED); // Send back parameter for channel above this line + } + else SendStatus(SEND_PARAMETERS | SEND_DEFFERED); + break; + case CH_VCTEMP: // moved + case CH_THERMO: ///? wasnt send before/ now will /// + setVal(Par[0]); // Store value + if (send) SendStatus(SEND_PARAMETERS | SEND_DEFFERED); // Send back parameter for channel above this line }//itemtype - lastctrl = millis(); //last controlled object ond timestamp update - lastobj = itemArr; - + if (! toExecute && itemType !=CH_GROUP) return 1; // Parameters are stored, no further action required break; case CMD_XON: - if (!isActive()) //if channel was'nt active before CMD_XON + if (!chActive>0) //if channel was'nt active before CMD_XON { debugSerial<0 && send) + { + SendStatus(SEND_COMMAND); + return 1; + } { short params = 0; - setCmd(cmd); //retrive stored values st.aslong = getVal(); @@ -458,14 +619,16 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send, int subItemN) if (st.aslong > 0) //Stored smthng switch (itemType) { - //case CH_GROUP: + case CH_GROUP: + if (send && !isActive()) SendStatus(SEND_COMMAND); // Just send ON, suppress send back ON of chan already active + break; case CH_RGBW: case CH_RGB: Par[0] = st.h; Par[1] = st.s; Par[2] = st.v; params = 3; - SendStatus(0, params, Par,true); // Send restored triplet. In any cases + if (send) SendStatus(SEND_COMMAND | SEND_PARAMETERS); // ???Send restored triplet. In any cases break; case CH_VCTEMP: @@ -475,15 +638,15 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send, int subItemN) case CH_VC: Par[0] = st.aslong; params = 1; - SendStatus(0, params, Par, true); // Send restored parameter, even if send=false - no problem, loop will be supressed at next hop + if (send) SendStatus(SEND_COMMAND | SEND_PARAMETERS); // ???Send restored parameter, even if send=false - no problem, loop will be supressed at next hop break; case CH_THERMO: Par[0] = st.aslong; params = 0; - if (send) SendStatus(CMD_ON); // Just ON (switch) + if (send) SendStatus(SEND_COMMAND); // Just ON (switch) break; default: - if (send) SendStatus(cmd); // Just send ON + if (send) SendStatus(SEND_COMMAND); // Just send ON }//itemtype switch else {// Default settings, values not stored yet debugSerial< 0) { + if (chActive>0) { Par[0] = 0; Par[1] = 0; Par[2] = 0; if (getCmd() == CMD_XON) setCmd(CMD_OFF); //Prevent restoring temporary turned on channels (by XON) else setCmd(cmd); - SendStatus(CMD_OFF); //HALT to OFF mapping - send in any cases + SendStatus(SEND_COMMAND); //HALT to OFF mapping - send in any cases debugSerial<type == aJson_Array) && ((numpar = aJson.getArraySize(itemArg)) >= 2)) { - int _addr = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_ADDR)->valueint; - int _reg = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG)->valueint; - int _mask = -1; - if (numpar >= (MODBUS_CMD_ARG_MASK+1)) _mask = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_MASK)->valueint; - int _maxval = 0x3f; - if (numpar >= (MODBUS_CMD_ARG_MAX_SCALE+1)) _maxval = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_MAX_SCALE)->valueint; - int _regType = MODBUS_HOLDING_REG_TYPE; - if (numpar >= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint; - if (_maxval) modbusDimmerSet(_addr, _reg, _regType, _mask, map(Par[0], 0, 100, 0, _maxval)); - else modbusDimmerSet(_addr, _reg, _regType, _mask, Par[0]); - } - break; - } + case CH_MODBUS: + modbusDimmerSet(Par[0]); + break; #endif + case CH_GROUP://Group { - //aJsonObject *groupArr= aJson.getArrayItem(itemArr, 1); if (itemArg->type == aJson_Array) { aJsonObject *i = itemArg->child; while (i) { Item it(i->valuestring); -// it.copyPar(itemVal); - it.Ctrl(cmd, n, Par, send,subItemN); //// was true + it.Ctrl(cmd, n, Par, send,suffixCode,subItem); //// was true i = i->next; } //while } //if @@ -729,11 +878,12 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send, int subItemN) } int Item::isActive() { - HSVstore st; + CHstore st; int val = 0; if (!isValid()) return -1; -//debugSerial<name); + debugSerial<name; + int cmd = getCmd(); @@ -743,32 +893,37 @@ int Item::isActive() { switch (cmd) { case CMD_ON: case CMD_XON: - //debugSerial<<" active"); + case CMD_AUTO: + case CMD_HEAT: + case CMD_COOL: + debugSerial<isActive(); st.aslong = getVal(); switch (itemType) { case CH_GROUP: //make recursive calculation - is it some active in group if (itemArg->type == aJson_Array) { - debugSerial<child; while (i) { Item it(i->valuestring); if (it.isValid() && it.isActive()) { - debugSerial<next; } //while + debugSerial< poll: 0A 03 08 34 00 0A 87 18 */ +#ifdef _modbus +int Item::modbusDimmerSet(uint16_t value) + { + switch (getCmd()) + { + case CMD_OFF: + case CMD_HALT: + value=0; + break; + } -void Item::mb_fail(short addr, short op, int val, int cmd) { + short numpar=0; + if ((itemArg->type == aJson_Array) && ((numpar = aJson.getArraySize(itemArg)) >= 2)) { + int _addr = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_ADDR)->valueint; + int _reg = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG)->valueint; + int _mask = -1; + if (numpar >= (MODBUS_CMD_ARG_MASK+1)) _mask = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_MASK)->valueint; + int _maxval = 0x3f; + if (numpar >= (MODBUS_CMD_ARG_MAX_SCALE+1)) _maxval = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_MAX_SCALE)->valueint; + int _regType = MODBUS_HOLDING_REG_TYPE; + if (numpar >= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint; + if (_maxval) modbusDimmerSet(_addr, _reg, _regType, _mask, map(value, 0, 100, 0, _maxval)); + else modbusDimmerSet(_addr, _reg, _regType, _mask, value); + } + } +#endif + +void Item::mb_fail() { debugSerial< 0) aJson.addNumberToObject(out, "pwr", pwr / 10.); else aJson.addNumberToObject(out, "pwr", 0); @@ -1070,13 +1258,13 @@ int Item::checkFM() { } boolean Item::checkModbusRetry() { - int cmd = getCmd(true); - if (cmd & CMD_RETRY) { // if last sending attempt of command was failed + int cmd = getCmd(); + if (getFlag(SEND_RETRY)) { // if last sending attempt of command was failed int val = getVal(); debugSerial<Status()) + { + driver->Poll(); + return INTERVAL_POLLING; //TODO refactoring + } + // Legacy polling switch (itemType) { case CH_MODBUS: checkModbusDimmer(); @@ -1198,114 +1393,178 @@ int Item::Poll() { sendDelayedStatus(); return INTERVAL_CHECK_MODBUS; break; - case CH_RGB: //All channels with slider generate too many updates + /* case CH_RGB: //All channels with slider generate too many updates case CH_RGBW: case CH_DIMMER: case CH_PWM: case CH_VCTEMP: case CH_THERMO: + case CH_GROUP:*/ + default: sendDelayedStatus(); } return INTERVAL_POLLING; } -void Item::sendDelayedStatus(){ - HSVstore st; - int cmd=getCmd(true); - short params = 0; - int Par[3]; - if (cmd & CMD_REPORT) +void Item::sendDelayedStatus() +{ + if (getFlag(SEND_COMMAND | SEND_PARAMETERS)) { - //retrive stored values - st.aslong = getVal(); - switch (itemType) { - //case CH_GROUP: - case CH_RGBW: - case CH_RGB: - Par[0] = st.h; - Par[1] = st.s; - Par[2] = st.v; - params = 3; - SendStatus(0, params, Par); // Send restored triplet. - break; - - case CH_VCTEMP: - case CH_PWM: - case CH_DIMMER: //Everywhere, in flat VAL - case CH_MODBUS: - case CH_VC: - case CH_THERMO: - - - Par[0] = st.aslong; - params = 1; - SendStatus(0, params, Par); // Send restored parameter - break; - default: - SendStatus(cmd); // Just send CMD - }//itemtype - cmd &= ~CMD_REPORT; // Clean report flag - setCmd(cmd); + SendStatus(SEND_COMMAND | SEND_PARAMETERS); + clearFlag(SEND_COMMAND | SEND_PARAMETERS); } } #endif -int Item::SendStatus(short cmd, short n, int *Par, boolean deffered) { - -/// ToDo: relative patches, configuration - int chancmd=getCmd(true); - if (deffered) { - setCmd(chancmd | CMD_REPORT); +int Item::SendStatus(int sendFlags) { + int chancmd=getCmd(); + if (sendFlags & SEND_DEFFERED) { + setFlag(sendFlags & (SEND_COMMAND | SEND_PARAMETERS)); debugSerial<name, sizeof(addrstr)); + if (mqttClient.connected() && !ethernetIdleCount) + { + if (sendFlags & SEND_PARAMETERS && chancmd != CMD_OFF && chancmd != CMD_HALT) + { + mqttClient.publish(addrstr, valstr, true); + debugSerial<")<")<")<name, sizeof(addrstr)); + strncat(addrstr, "/", sizeof(addrstr)); + strncat_P(addrstr, SET_P, sizeof(addrstr)); + + + debugSerial<")<name, sizeof(addrstr)); + strncat(addrstr, "/", sizeof(addrstr)); + strncat_P(addrstr, CMD_P, sizeof(addrstr)); + + debugSerial<")<type == aJson_Array && aJson.getArraySize(item)>1) { Item it(item); - if (it.isValid()) { + if (it.isValid() && !it.Setup()) { + //Legacy Setup short inverse = 0; int pin=it.getArg(); if (pin<0) {pin=-pin; inverse = 1;} @@ -1140,7 +1142,7 @@ void cmdFunctionPwd(int arg_cnt, char **args) } void cmdFunctionSetMac(int arg_cnt, char **args) { - if (sscanf(args[1], "%x:%x:%x:%x:%x:%x%с", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) < 6) { + if (sscanf(args[1], "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) < 6) { debugSerial<MAXFLASHSTR-1) len=MAXFLASHSTR-1; for(int i=0;i nextPollingCheck) { while (pollingItem && !done) { if (pollingItem->type == aJson_Array) { @@ -1761,7 +1764,7 @@ void pollingLoop(void) { } //while }//if } -#endif +//#endif bool isThermostatWithMinArraySize(aJsonObject *item, int minimalArraySize) { return (item->type == aJson_Array) && (aJson.getArrayItem(item, I_TYPE)->valueint == CH_THERMO) && @@ -1769,8 +1772,15 @@ bool isThermostatWithMinArraySize(aJsonObject *item, int minimalArraySize) { } bool thermoDisabledOrDisconnected(aJsonObject *thermoExtensionArray, int thermoStateCommand) { - return thermoStateCommand == CMD_OFF || thermoStateCommand == CMD_HALT || - aJson.getArrayItem(thermoExtensionArray, IET_ATTEMPTS)->valueint == 0; + if (aJson.getArrayItem(thermoExtensionArray, IET_ATTEMPTS)->valueint == 0) return true; + switch (thermoStateCommand) { + case CMD_ON: + case CMD_XON: + case CMD_AUTO: + case CMD_HEAT: + return false; + default: return true; + } } diff --git a/lighthub/modules/in_ccs811_hdc1080.cpp b/lighthub/modules/in_ccs811_hdc1080.cpp index b3aa18f..9ea2aec 100644 --- a/lighthub/modules/in_ccs811_hdc1080.cpp +++ b/lighthub/modules/in_ccs811_hdc1080.cpp @@ -17,7 +17,7 @@ static bool HDC1080ready = false; static bool CCS811ready = false; -int in_ccs811::Setup(int addr) +int in_ccs811::Setup() { if (CCS811ready) {debugSerial<itemArr->name, "ON","/fresh"); + else publishTopic(item->itemArr->name, "OFF","/fresh"); + + ///////////////////////////////// + if (lock_rem == 0x80){ + publishTopic(item->itemArr->name, "ON","/lock"); + } + if (lock_rem == 0x00){ + publishTopic(item->itemArr->name, "OFF","/lock"); + } + ///////////////////////////////// + /* + if (power == 0x01 || power == 0x11){ + publishTopic(item->itemArr->name,"Power", "on"); + } + if (power == 0x00 || power == 0x10){ + publishTopic(item->itemArr->name,"Power", "off"); + } + */ + + Serial.print ("Power="); + Serial.println(power); + + if (power & 0x08) + publishTopic(item->itemArr->name, "ON", "/quiet"); + else publishTopic(item->itemArr->name, "OFF" , "/quiet"); + + + if (power == 3 || power == 2) + publishTopic(item->itemArr->name, "on","/compressor"); + else + publishTopic(item->itemArr->name, "off","/compressor"); + + + publishTopic(item->itemArr->name, (long) swing,"/swing"); + publishTopic(item->itemArr->name, (long) fan_spd,"/fan"); + + ///////////////////////////////// +/* + if (swing == 0x00){ + publishTopic(item->itemArr->name, "off","swing"); + } + if (swing == 0x01){ + publishTopic(item->itemArr->name, "ud","swing"); + } + if (swing == 0x02){ + publishTopic(item->itemArr->name, "lr","swing"); + } + if (swing == 0x03){ + publishTopic(item->itemArr->name, "all","swing"); + } + ///////////////////////////////// + if (fan_spd == 0x00){ + publishTopic(item->itemArr->name, "max","fan"); + } + if (fan_spd == 0x01){ + publishTopic(item->itemArr->name, "mid","fan"); + } + if (fan_spd == 0x02){ + publishTopic(item->itemArr->name, "min","fan"); + } + if (fan_spd == 0x03){ + publishTopic(item->itemArr->name, "auto","fan"); + } + */ + ///////////////////////////////// + + publishTopic(item->itemArr->name,(long)set_tmp,"/set"); + publishTopic(item->itemArr->name, (long)cur_tmp, "/temp"); + //////////////////////////////////// + s_mode[0]='\0'; + + if (mode == 0x00){ + strcpy_P(s_mode,AUTO_P); + } + else if (mode == 0x01){ + strcpy_P(s_mode,COOL_P); + } + else if (mode == 0x02){ + strcpy_P(s_mode,HEAT_P); + } + else if (mode == 0x03){ + strcpy_P(s_mode,FAN_ONLY_P); + } + else if (mode == 0x04){ + strcpy_P(s_mode,DRY_P); + } + + publishTopic(item->itemArr->name, (long) mode, "/mode"); + + if (power & 0x01) + publishTopic(item->itemArr->name, s_mode,"/cmd"); + + else publishTopic(item->itemArr->name, "OFF","/cmd"); + + String raw_str; + char raw[75]; + for (int i=0; i < 37; i++){ + if (data[i] < 10){ + raw_str += "0"; + raw_str += String(data[i], HEX); + } else { + raw_str += String(data[i], HEX); + } + } + raw_str.toUpperCase(); + raw_str.toCharArray(raw,75); + publishTopic(item->itemArr->name, raw,"/raw"); + Serial.println(raw); + +/////////////////////////////////// +} + +byte getCRC(byte req[], size_t size){ + byte crc = 0; + for (int i=2; i < size; i++){ + crc += req[i]; + } + return crc; +} + +void SendData(byte req[], size_t size){ + AC_Serial.write(req, size - 1); + AC_Serial.write(getCRC(req, size-1)); + AC_Serial.flush(); +} + +inline unsigned char toHex( char ch ){ + return ( ( ch >= 'A' ) ? ( ch - 'A' + 0xA ) : ( ch - '0' ) ) & 0x0F; +} + + + +int out_AC::Setup() +{ +Serial.println("AC Init"); +AC_Serial.begin(9600); +driverStatus = CST_INITIALIZED; +return 1; +} + +int out_AC::Stop() +{ +Serial.println("AC De-Init"); + +driverStatus = CST_UNKNOWN; +return 1; +} + +int out_AC::Status() +{ +return driverStatus; +} + +int out_AC::isActive() +{ +return (power & 1); +} + +int out_AC::Poll() +{ + //debugSerial<<"."; + +long now = millis(); + if (now - prevPolling > INTERVAL_AC_POLLING) { + prevPolling = now; + Serial.println ("Polling"); + SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера + } +delay(100); + if(AC_Serial.available() > 0){ + AC_Serial.readBytes(data, 37); + while(AC_Serial.available()){ + delay(2); + AC_Serial.read(); + } + if (data[36] != inCheck){ + inCheck = data[36]; + InsertData(data, 37); + } + } +return 1; +}; + +int out_AC::Ctrl(short cmd, short n, int * Parameters, boolean send, int suffixCode, char* subItem) +{ + // Some additional Subitems + if (strcmp_P(subItem, LOCK_P) == 0) suffixCode = S_LOCK; + else if (strcmp_P(subItem, SWING_P) == 0) suffixCode = S_SWING; + else if (strcmp_P(subItem, QUIET_P) == 0) suffixCode = S_QUIET; + else if (strcmp_P(subItem, RAW_P) == 0) suffixCode = S_RAW; + + data[B_POWER] = power; + // debugSerial<= 0 && set_tmp <= 30) + { + data[B_SET_TMP] = set_tmp; + } + break; + + case S_CMD: + switch (cmd) + { + case CMD_ON: + data[B_POWER] |= 1; + SendData(on, sizeof(on)/sizeof(byte)); + return 1; + break; + case CMD_OFF: + case CMD_HALT: + data[B_POWER] = 0; + SendData(off, sizeof(off)/sizeof(byte)); + return 1; + break; + case CMD_AUTO: + data[B_MODE] = 0; + data[B_POWER] |= 1; + break; + case CMD_COOL: + data[B_MODE] = 1; + data[B_POWER] |= 1; + break; + case CMD_HEAT: + data[B_MODE] = 2; + data[B_POWER] |= 1; + break; + case CMD_DRY: + data[B_MODE] = 4; + data[B_POWER] |= 1; + break; + case CMD_FAN: + data[B_MODE] = 3; + data[B_POWER] |= 1; + break; + case CMD_UNKNOWN: + return -1; + break; + } + break; + + case S_FAN: + data[B_FAN_SPD] = Parameters[0]; + break; + + case S_MODE: + data[B_MODE] = Parameters[0]; + break; + + case S_LOCK: + switch (cmd) + { + case CMD_ON: + data[B_LOCK_REM] = 80; + break; + case CMD_OFF: + data[B_LOCK_REM] = 0; + break; + } + break; + + case S_SWING: + data[B_SWING] = Parameters[0]; + break; + + case S_QUIET: + switch (cmd) + { + case CMD_ON: + data[B_POWER] |= 8; + break; + case CMD_OFF: + data[B_POWER] &= ~8; + break; + } + + + break; + + case S_RAW: + /* + { + char buf[75]; + char hexbyte[3] = {0}; + strPayload.toCharArray(buf, 75); + int octets[sizeof(buf) / 2] ; + for (int i=0; i < 76; i += 2){ + hexbyte[0] = buf[i] ; + hexbyte[1] = buf[i+1] ; + data[i/2] = (toHex(hexbyte[0]) << 4) | toHex(hexbyte[1]); + + + + AC_Serial.write(data, 37); + AC_Serial.flush(); + + publishTopic("RAW", buf); + } + */ + + break; + + case S_NOTFOUND: + return -1; + + } + +/* + ////////// + if (strTopic == "/myhome/in/Conditioner/Fan_Speed"){ + if (strPayload == "max"){ + data[B_FAN_SPD] = 0; + } + if (strPayload == "mid"){ + data[B_FAN_SPD] = 1; + } + if (strPayload == "min"){ + data[B_FAN_SPD] = 2; + } + if (strPayload == "auto"){ + data[B_FAN_SPD] = 3; + } + } + //////// + if (strTopic == "/myhome/in/Conditioner/Swing"){ + if (strPayload == "off"){ + data[B_SWING] = 0; + } + if (strPayload == "ud"){ + data[B_SWING] = 1; + } + if (strPayload == "lr"){ + data[B_SWING] = 2; + } + if (strPayload == "all"){ + data[B_SWING] = 3; + } + } + //////// + if (strTopic == "/myhome/in/Conditioner/Lock_Remote"){ + if (strPayload == "true"){ + data[B_LOCK_REM] = 80; + } + if (strPayload == "false"){ + data[B_LOCK_REM] = 0; + } + } + //////// + if (strTopic == "/myhome/in/Conditioner/Power"){ + if (strPayload == "off" || strPayload == "false" || strPayload == "0"){ + SendData(off, sizeof(off)/sizeof(byte)); + return; + } + if (strPayload == "on" || strPayload == "true" || strPayload == "1"){ + SendData(on, sizeof(on)/sizeof(byte)); + return; + } + if (strPayload == "quiet"){ + data[B_POWER] = 9; + } + } + */ + //////// + //if (strTopic == "/myhome/in/Conditioner/RAW") + + data[B_CMD] = 0; + data[9] = 1; + data[10] = 77; + data[11] = 95; + SendData(data, sizeof(data)/sizeof(byte)); + return 1; +} + + + +#endif diff --git a/lighthub/modules/out_ac.h b/lighthub/modules/out_ac.h new file mode 100644 index 0000000..9d1d123 --- /dev/null +++ b/lighthub/modules/out_ac.h @@ -0,0 +1,37 @@ + +#pragma once +#ifndef AC_DISABLE +#include + +#define LEN_B 37 +#define B_CUR_TMP 13 //Текущая температура +#define B_CMD 17 // 00-команда 7F-ответ ??? +#define B_MODE 23 //04 - DRY, 01 - cool, 02 - heat, 00 - smart 03 - вентиляция +#define B_FAN_SPD 25 //Скорость 02 - min, 01 - mid, 00 - max, 03 - auto +#define B_SWING 27 //01 - верхний и нижний предел вкл. 00 - выкл. 02 - левый/правый вкл. 03 - оба вкл +#define B_LOCK_REM 28 //80 блокировка вкл. 00 - выкл +#define B_POWER 29 //on/off 01 - on, 00 - off (10, 11)-Компрессор??? 09 - QUIET +#define B_FRESH 31 //fresh 00 - off, 01 - on +#define B_SET_TMP 35 //Установленная температура + +#define S_LOCK S_ADDITIONAL+1 +#define S_QUIET S_ADDITIONAL+2 +#define S_SWING S_ADDITIONAL+3 +#define S_RAW S_ADDITIONAL+4 + +extern void modbusIdle(void) ; +class out_AC : public abstractOut { +public: + + out_AC(Item * _item):abstractOut(_item){}; + int Setup() override; + int Poll() override; + int Stop() override; + int Status() override; + int isActive() override; + int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true, int suffixCode=0, char* subItem=NULL) override; + +protected: + void InsertData(byte data[], size_t size); +}; +#endif diff --git a/lighthub/modules/out_spiled.cpp b/lighthub/modules/out_spiled.cpp new file mode 100644 index 0000000..90fa4b1 --- /dev/null +++ b/lighthub/modules/out_spiled.cpp @@ -0,0 +1,97 @@ +#ifndef SPILED_DISABLE + +#include "modules/out_spiled.h" +#include "Arduino.h" +#include "options.h" +#include "Streaming.h" +#include "FastLED.h" +#include "item.h" + +#define NUM_LEDS 15 +#define DATA_PIN 4 + +static CRGB leds[NUM_LEDS]; +static int driverStatus = CST_UNKNOWN; + +int out_SPILed::Setup() +{ +Serial.println("SPI-LED Init"); +FastLED.addLeds(leds, NUM_LEDS); +driverStatus = CST_INITIALIZED; +return 1; +} + +int out_SPILed::Stop() +{ +Serial.println("SPI-LED De-Init"); +//FastLED.addLeds(leds, NUM_LEDS); +FastLED.clear(true); +driverStatus = CST_UNKNOWN; +return 1; +} + +int out_SPILed::Status() +{ +return driverStatus; +} + +int out_SPILed::isActive() +{ + +} + +int out_SPILed::Poll() +{ + //FastLED.show(); +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; + +if (subItem) +{ //Just single LED to control + from=atoi(subItem); + to=from; +} +debugSerial< + +class out_SPILed : public abstractOut { +public: + + out_SPILed(Item * _item):abstractOut(_item){}; + int Setup() override; + int Poll() override; + int Stop() override; + int Status() override; + int isActive() override; + int Ctrl(short cmd, short n=0, int * Parameters=NULL, boolean send=true, int suffixCode=0, char* subItem=NULL) override; + +protected: +}; +#endif diff --git a/lighthub/options.h b/lighthub/options.h index 8a16ef6..b12b0cb 100644 --- a/lighthub/options.h +++ b/lighthub/options.h @@ -18,7 +18,7 @@ #define THERMO_OVERHEAT_CELSIUS 38. #define FM_OVERHEAT_CELSIUS 40. -#define MIN_VOLUME 10 +#define MIN_VOLUME 25 #define INIT_VOLUME 50 #define MAXFLASHSTR 32