2nd Salinity module w/Cloud Wifi Hub

Expansion modules and attachments
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Thank you, libraries updated and recompiling.

Lot's of warnings/notes (I took it off verbose) but it did compile (used 2.3.).

Code: Select all

Build options changed, rebuilding all
C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: In function 'unsigned int crc16(int*, byte)':

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:172:8: warning: unused variable 'temp' [-Wunused-variable]

   byte temp = 0;

        ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:173:7: warning: unused variable 'test' [-Wunused-variable]

   int test;

       ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: In function 'void reconnect()':

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:224:34: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

       Publish(pub_buffer, "all:0");

                                  ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: At global scope:

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:272:6: warning: unused parameter 'myWiFiManager' [-Wunused-parameter]

 void configModeCallback (WiFiManager *myWiFiManager) {

      ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: In function 'void callback(char*, byte*, unsigned int)':

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:295:23: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

   for (int i = 0; i < length; i++) {

                       ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:632:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

     for (int a = 0; a < length; a++)

                         ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: At global scope:

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:288:6: warning: unused parameter 'topic' [-Wunused-parameter]

 void callback(char* topic, byte* payload, unsigned int length) {

      ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: In function 'void setup()':

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:859:59: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long int' [-Wformat=]

   sprintf(clientid, "%s%02d", mqtt_username, random(10000));

                                                           ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:859:59: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino: In function 'void loop()':

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:897:94: warning: 't_httpUpdate_return ESP8266HTTPUpdate::update(const String&, uint16_t, const String&, const String&)' is deprecated (declared at C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266httpUpdate\src/ESP8266httpUpdate.h:100) [-Wdeprecated-declarations]

       ESPhttpUpdate.update("forum.reefangel.com", 80, "/firmware/CloudWifiESP8266Hub.ino.bin");

                                                                                              ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1098:51: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

         sprintf(buffer, "%sc:%d", pub_orp, temporp);

                                                   ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1098:51: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1133:56: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

         sprintf(buffer, "%sc:%d", pub_salinity, tempsal);

                                                        ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1133:56: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1169:55: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

         sprintf(buffer, "%sc:%d", pub_phexp, tempphexp);

                                                       ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1169:55: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1230:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

         if (crc == crc16(reply, 4))

                                  ^

In file included from sketch\Cloud_Wifi_Hub_Sal.ino.cpp:1:0:

C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\cores\esp8266/Arduino.h:136:44: warning: comparison is always false due to limited range of data type [-Wtype-limits]

 #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

                                            ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1292:26: note: in expansion of macro 'constrain'

           Params.WL[i] = constrain(Params.WL[i], 0, 255);

                          ^

C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\cores\esp8266/Arduino.h:136:64: warning: comparison is always false due to limited range of data type [-Wtype-limits]

 #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

                                                                ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1292:26: note: in expansion of macro 'constrain'

           Params.WL[i] = constrain(Params.WL[i], 0, 255);

                          ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1299:60: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

               sprintf(buffer, "%s%d", pub_custom_wl, tempwl);

                                                            ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1299:60: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1301:55: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

               sprintf(buffer, "%sc:%d", pub_wl, tempwl);

                                                       ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1301:55: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1306:65: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

               sprintf(buffer, "%s%d", pub_custom_multiwl, tempwl);

                                                                 ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1306:65: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1308:60: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

               sprintf(buffer, "%sc:%d", pub_multiwl, tempwl);

                                                            ^

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:1308:60: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]

In file included from C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:13:0:

C:\Users\Loose\Documents\Arduino\libraries\CloudGlobals/CloudGlobals.h: At global scope:

C:\Users\Loose\Documents\Arduino\libraries\CloudGlobals/CloudGlobals.h:96:13: warning: 'username' defined but not used [-Wunused-variable]

 static char username[16];

             ^

C:\Users\Loose\Documents\Arduino\libraries\CloudGlobals/CloudGlobals.h:97:13: warning: 'password' defined but not used [-Wunused-variable]

 static char password[16];

             ^

C:\Users\Loose\Documents\Arduino\libraries\CloudGlobals/CloudGlobals.h:154:16: warning: 'FoundIP' defined but not used [-Wunused-variable]

 static boolean FoundIP=false;

                ^

C:\Users\Loose\Documents\Arduino\libraries\PubSubClient\PubSubClient.cpp: In member function 'boolean PubSubClient::subscribe(const char*, uint8_t)':

C:\Users\Loose\Documents\Arduino\libraries\PubSubClient\PubSubClient.cpp:492:15: warning: comparison is always false due to limited range of data type [-Wtype-limits]

     if (qos < 0 || qos > 1) {

               ^

C:\Users\Loose\Documents\Arduino\libraries\WiFiManager\WiFiManager.cpp: In member function 'boolean WiFiManager::isIp(String)':

C:\Users\Loose\Documents\Arduino\libraries\WiFiManager\WiFiManager.cpp:780:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

   for (int i = 0; i < str.length(); i++) {

                                  ^

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp: In member function 'uint8_t OneWire::reset()':

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp:145:24: warning: unused variable 'reg' [-Wunused-variable]

  volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;

                        ^

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp: In member function 'void OneWire::write_bit(uint8_t)':

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp:179:24: warning: unused variable 'reg' [-Wunused-variable]

  volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;

                        ^

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp: In member function 'uint8_t OneWire::read_bit()':

C:\Users\Loose\Documents\Arduino\libraries\OneWire\OneWire.cpp:207:24: warning: unused variable 'reg' [-Wunused-variable]

  volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;

                        ^

Archiving built core (caching) in: C:\Users\Loose\AppData\Local\Temp\arduino_cache_555022\core\core_esp8266_esp8266_huzzah_xtal_80,vt_flash,exception_disabled,eesz_4M,ip_lm2f,dbg_Disabled,lvl_None____,wipe_none,baud_115200_af310de3343d0ab5be8a323c884dd04a.a
Sketch uses 403348 bytes (38%) of program storage space. Maximum is 1044464 bytes.
Global variables use 36972 bytes (45%) of dynamic memory, leaving 44948 bytes for local variables. Maximum is 81920 bytes.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Good.
So, in that code, replace this:

Code: Select all

#define CloudCustomModule1  CUSTOM_NONE
With this:

Code: Select all

#define CloudCustomModule1  CUSTOM_SALINITY
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Modified and compiled successfully.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Ok, upload to your cloud expansion and plug in the salinity module to it.
It should start sending data as custom expansion 1. You may need to calibrate.
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Code has been uploaded but once finished it it did reconnect to my local Wifi but it seems to be having trouble connecting to the cloud server (Blinking Magenta).

I can get it to fully connect with the reset/setup procedure (paper clip) and I can control my lights with the web uapp and the Android app on my phone but, if I take power away and then plug it back in, it will not reconnect to the server automatically.

Also, once connected how/where can I see the data from the salinity probe/custom expansion 1? I enabled Custom variables on the Android app but nothing is registering on Custom 0-7.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Sorry.
I forgot that we need to edit the cloud settings.
Open the file RA_CustomSettings.h and change the CLOUD_USERNAME and CLOUD_PASSWORD.
The Custom expansion 1 will show up on the screen of RA* only :(
We don't have any app that can display it too.
You can as a work around, assign a custom variable to have the 2nd salinity, but it will not have the decimal point. It would show for example 350 instead of 35.0
To do that, add this to your loop():

Code: Select all

ReefAngel.CustomVar[0]=ReefAngel.CustomExpansionValue[0];
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

RA_CustomSettings.h modified. Do I need to upload directly to the Cloud Wifi hub again or will changing the file be sufficient?

"ReefAngel.CustomVar[0]=ReefAngel.CustomExpansionValue[0];" added to my loop()

Now, I'm sorry but, decimal points, LOL! The old Naval aviator here can translate that little dot on the fly :D.

The only problem I've got is the RA* rebooting when I touch the screen and move from one screen to the other; annoying but not a show stopper.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Readings are odd. I put the second probe in the display tank next to the DT probe (which is stable @30.3) and am getting values from 215 to 8; currently averaging 80.

Thoughts?
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Did you try calibrating it?
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

So, I tried calibrating Custom Expansion Module 1 about 5 times from the RA* screen.

#1 - First 35ppt then RODI - Calibration value for both was 0. RA* Custom Expansion Module 1 showed 00.-29 <--- that is not a typo. ;)

#2 - First RODI then 35ppt - Calibration value for both was 0. Android app showed constant 61; can't tell you what the RA* showed as it displayed overlapping numbers from top to bottom in that column, screen went blank, and it rebooted.

#3 - I cancelled this attempt because I started with RODI and then the next message was new as it said to put the probe in RODI and press OK.

#4 - 35ppt then RODI then 35ppt - Calibration value for both was 0. RA* went blank and rebooted when I tried to change menu pages, Android app showed 84, 88, then 224.

#5 - RODI then RODI then 35ppt - Calibration value for both was 0. App shows 0 with the probe in my DT.

It's late so I'm done for the evening.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

If you open Serial monitor on Arudino, it should start displaying the log.
Can you record the log of when you start the salinity calibrating and post here?
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Sure thing.

I did the full cal but am only posting from the start (35ppt solution) to the RODI to just putting the probe back into the 35ppt.

Code: Select all

cloud:PWMD:52
cloud:PWMD2:92
cloud:WL1:96
cloud:T3:768
cloud:PWMD:50
cloud:PWMD2:94
cloud:WL1:93
cloud:T3:766
cloud:CEXP0C:1
Custom Exp calibration
CEXP0C:1
cloud:PWMD:49
cloud:PWMD2:95
cloud:WL1:96
Loose/in: cexp:0:c:1828
cloud:PWMD:46
cloud:PWMD2:98
cloud:C0:84
cloud:CEXP0:-12460
Loose/in: cexp:0:c:1827
cloud:C0:83
cloud:CEXP0:-12461
Loose/in: cexp:0:c:1829
cloud:PWMD:45
cloud:PWMD2:99
cloud:C0:85
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1828
cloud:C0:84
Loose/in: cexp:0:c:1829
cloud:CEXP0:-12460
cloud:C0:85
Loose/in: cexp:0:c:1829
cloud:T3:768
cloud:PH:821
cloud:CEXP0:-12459
cloud:PWME1:20
PWME1:20
Loose/in: cexp:0:c:1830
cloud:PWMD:46
Loose/in: cexp:0:c:1829
cloud:PWMD2:98
cloud:WL1:97
cloud:C0:86
cloud:PH:820
cloud:CEXP0:-12458
cloud:PWMD:47
cloud:PWMD2:97
cloud:WL1:96
cloud:C0:85
cloud:T3:766
cloud:PH:821
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1829
cloud:PWMD:48
Loose/in: cexp:0:c:1829
cloud:PWMD2:96
cloud:T1:719
cloud:T3:768
cloud:PH:820
cloud:PWMD:49
Loose/in: cexp:0:c:1829
cloud:PWMD2:95
cloud:WL1:97
cloud:PWMD:51
cloud:PWMD2:93
cloud:WL1:96
cloud:T3:766
Loose/in: cexp:0:c:1829
cloud:PWMD:53
cloud:PWMD2:91
cloud:T3:768
Loose/in: cexp:0:c:1828
cloud:PWMD:55
Loose/in: cexp:0:c:1828
cloud:PWMD2:89
cloud:WL1:97
cloud:C0:84
cloud:T1:717
cloud:CEXP0:-12460
cloud:PWMD:57
Loose/in: cexp:0:c:1829
cloud:PWMD2:87
cloud:WL1:95
cloud:T1:719
Loose/in: cexp:0:c:1829
cloud:PWMD:59
cloud:PWMD2:85
cloud:WL1:97
cloud:C0:85
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1827
cloud:PWMD:62
cloud:PWMD2:82
cloud:WL1:95
cloud:C0:83
cloud:T3:766
cloud:PH:821
cloud:SAL:306
cloud:CEXP0:-12461
Loose/in: cexp:0:c:1829
cloud:PWMD:64
cloud:PWMD2:80
cloud:WL1:94
cloud:T3:768
cloud:PH:820
cloud:SAL:305
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1829
cloud:PWMD:67
cloud:PWMD2:77
cloud:WL1:96
cloud:C0:85
cloud:T1:717
cloud:T3:766
Loose/in: cexp:0:c:1829
cloud:PWMD:69
cloud:PWMD2:75
cloud:WL1:95
cloud:T1:719
cloud:SAL:306
Loose/in: cexp:0:c:1829
cloud:PWMD:72
cloud:PWMD2:72
cloud:WL1:96
cloud:T3:768
Loose/in: cexp:0:c:1828
cloud:PWMD:75
cloud:PWMD2:69
cloud:C0:84
cloud:SAL:305
cloud:CEXP0:-12460
Loose/in: cexp:0:c:1828
cloud:PWMD:77
cloud:PWMD2:67
Loose/in: cexp:0:c:1829
cloud:PWMD:80
cloud:PWMD2:64
cloud:WL1:95
cloud:C0:85
cloud:SAL:306
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1829
cloud:PWMD:82
cloud:PWMD2:62
cloud:WL1:96
cloud:SAL:305
Loose/in: cexp:0:c:1829
cloud:PWMD:85
cloud:PWMD2:59
cloud:PH:821
cloud:SAL:306
Loose/in: cexp:0:c:1829
cloud:PWMD:87
cloud:PWMD2:57
cloud:WL1:95
cloud:PH:820
cloud:SAL:305
Loose/in: cexp:0:c:1830
cloud:PWMD:89
cloud:PWMD2:55
cloud:C0:86
cloud:CEXP0:-12458
Loose/in: cexp:0:c:1830
cloud:PWMD:91
cloud:PWMD2:53
cloud:WL1:97
cloud:T3:766
Loose/in: cexp:0:c:1829
cloud:PWMD:93
cloud:R1:193
R1:193
cloud:PWMD2:51
cloud:WL1:0
cloud:WL2:0
cloud:WL3:0
cloud:WL4:0
cloud:C0:85
cloud:PH:821
cloud:SAL:60
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1829
cloud:PWMD:95
cloud:PWMD2:49
cloud:PH:820
Loose/in: cexp:0:c:1829
cloud:PWMD:96
cloud:PWMD2:48
Loose/in: cexp:0:c:1828
cloud:PWMD:98
cloud:PWMD2:46
cloud:C0:84
cloud:CEXP0:-12460
Loose/in: cexp:0:c:1829
cloud:PWMD:99
cloud:PWMD2:45
cloud:C0:85
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1828
cloud:C0:84
cloud:PH:821
cloud:CEXP0:-12460
Loose/in: cexp:0:c:1829
cloud:C0:85
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1829
Loose/in: cexp:0:c:1829
cloud:PWMD:98
cloud:PWMD2:46
cloud:PH:820
Loose/in: cexp:0:c:1828
cloud:C0:84
cloud:PH:821
cloud:CEXP0:-12460
Loose/in: cexp:0:c:1828
cloud:PWMD:97
cloud:R1:195
R1:195
cloud:PWMD2:47
cloud:WL1:96
cloud:WL2:90
cloud:WL3:3
cloud:WL4:1
cloud:PH:820
cloud:SAL:305
Loose/in: cexp:0:c:1829
cloud:PWMD:95
cloud:PWMD2:49
cloud:WL1:95
cloud:WL2:87
cloud:C0:85
cloud:SAL:306
cloud:CEXP0:-12459
Loose/in: cexp:0:c:1827
cloud:PWMD:94
cloud:PWMD2:50
cloud:WL1:96
cloud:WL2:90
cloud:C0:83
cloud:CEXP0:-12461
Loose/in: cexp:0:c:1827
cloud:PWMD:92
cloud:PWMD2:52
cloud:WL1:98
cloud:WL2:92
cloud:PH:821
cloud:SAL:305
Loose/in: cexp:0:c:1826
cloud:PWMD:90
cloud:PWMD2:54
cloud:WL1:100
Loose/in: cexp:0:c:1826
cloud:WL2:93
cloud:C0:82
cloud:CEXP0:-12462
cloud:PWMD:88
Loose/in: cexp:0:c:1826
cloud:PWMD2:56
cloud:WL1:97
cloud:WL2:94
cloud:PH:820
cloud:PWMD:86
Loose/in: cexp:0:c:1825
cloud:PWMD2:58
cloud:WL1:101
cloud:WL2:95
cloud:PWMD:84
Loose/in: cexp:0:c:1825
cloud:PWMD2:60
cloud:WL2:96
cloud:C0:81
cloud:CEXP0:-12463
cloud:PWMD:81
cloud:PWMD2:63
cloud:WL1:103
cloud:WL2:97
cloud:SAL:306
Loose/in: cexp:0:c:1826
cloud:PWMD:79
Loose/in: cexp:0:c:1825
cloud:PWMD2:65
cloud:WL2:96
cloud:C0:82
cloud:T1:721
cloud:SAL:305
cloud:CEXP0:-12462
cloud:PWMD:76
Loose/in: cexp:0:c:1715
cloud:PWMD2:68
cloud:WL1:101
cloud:C0:81
cloud:CEXP0:-12463
cloud:PWMD:73
Loose/in: cexp:0:c:781
cloud:PWMD2:71
cloud:WL1:103
cloud:WL2:95
cloud:C0:227
cloud:T1:719
cloud:CEXP0:-12573
Loose/in: cexp:0:c:363
cloud:PWMD:71
cloud:PWMD2:73
cloud:WL1:100
cloud:WL2:94
cloud:C0:69
cloud:CEXP0:-14173
Loose/in: cexp:0:c:173
cloud:PWMD:68
cloud:PWMD2:76
cloud:C0:163
cloud:PH:819
cloud:CEXP0:-14363
Loose/in: cexp:0:c:85
cloud:PWMD:65
cloud:PWMD2:79
cloud:WL1:99
cloud:WL2:93
cloud:C0:229
cloud:PH:820
cloud:SAL:306
cloud:CEXP0:5185
Loose/in: cexp:0:c:43
cloud:PWMD:63
cloud:PWMD2:81
cloud:WL2:92
cloud:C0:23
cloud:T1:721
cloud:SAL:305
cloud:CEXP0:5143
Loose/in: cexp:0:c:23
cloud:PWMD:60
cloud:PWMD2:84
cloud:WL1:96
cloud:WL2:91
cloud:PH:821
cloud:CEXP0:5123
Loose/in: cexp:0:c:13
cloud:PWMD:58
cloud:PWMD2:86
cloud:WL1:98
cloud:C0:249
cloud:PH:820
cloud:CEXP0:5113
Loose/in: cexp:0:c:8
cloud:PWMD:56
cloud:PWMD2:88
cloud:WL1:93
cloud:WL2:89
cloud:C0:6
cloud:T1:719
cloud:CEXP0:518
Loose/in: cexp:0:c:6
cloud:PWMD:54
cloud:PWMD2:90
cloud:WL1:95
cloud:C0:4
cloud:T1:721
cloud:CEXP0:516
Loose/in: cexp:0:c:4
cloud:PWMD:52
cloud:PWMD2:92
cloud:WL2:88
cloud:C0:2
cloud:CEXP0:514
Loose/in: cexp:0:c:3
cloud:PWMD:50
cloud:PWMD2:94
cloud:WL1:93
cloud:WL2:87
cloud:C0:1
cloud:T1:719
cloud:CEXP0:513
Loose/in: cexp:0:c:3
cloud:PWMD:49
cloud:PWMD2:95
cloud:WL1:91
cloud:WL2:86
cloud:T1:721
Loose/in: cexp:0:c:2
cloud:PWMD:47
cloud:PWMD2:97
cloud:WL1:88
cloud:WL2:85
cloud:C0:0
cloud:CEXP0:512
Loose/in: cexp:0:c:2
cloud:PWMD:46
cloud:PWMD2:98
cloud:WL1:99
cloud:WL2:84
cloud:PWME0:18
PWME0:18
cloud:PH:821
Loose/in: cexp:0:c:2
cloud:PWMD:45
cloud:PWMD2:99
cloud:WL1:98
cloud:PH:820
Loose/in: cexp:0:c:1
cloud:WL1:93
cloud:WL2:83
cloud:C0:255
cloud:CEXP0:511
Loose/in: cexp:0:c:1
cloud:WL1:97
cloud:WL2:82
Loose/in: cexp:0:c:1
cloud:WL1:94
cloud:WL2:81
cloud:PH:821
Loose/in: cexp:0:c:1
cloud:PWMD:46
cloud:PWMD2:98
cloud:WL1:97
cloud:PH:820
Loose/in: cexp:0:c:1
cloud:PWMD:47
cloud:PWMD2:97
cloud:WL1:95
Loose/in: cexp:0:c:1
cloud:PWMD:48
cloud:PWMD2:96
cloud:WL1:97
Loose/in: cexp:0:c:1
cloud:PWMD:49
cloud:PWMD2:95
Loose/in: cexp:0:c:1
cloud:PWMD:51
cloud:PWMD2:93
cloud:WL1:96
Loose/in: cexp:0:c:1
cloud:PWMD:53
cloud:PWMD2:91
cloud:WL1:97
cloud:WL2:82
Loose/in: cexp:0:c:163
cloud:PWMD:55
cloud:PWMD2:89
cloud:WL1:96
cloud:C0:219
cloud:CEXP0:-14373
Loose/in: cexp:0:c:1066
cloud:PWMD:57
cloud:PWMD2:87
cloud:WL1:94
cloud:C0:90
cloud:CEXP0:-13222
Loose/in: cexp:0:c:1470
cloud:PWMD:59
cloud:PWMD2:85
cloud:WL1:96
cloud:C0:238
cloud:CEXP0:-12818
Loose/in: cexp:0:c:1662
cloud:PWMD:62
cloud:PWMD2:82
cloud:WL1:95
cloud:WL2:81
cloud:C0:174
cloud:PH:821
cloud:CEXP0:-12626
Loose/in: cexp:0:c:1753
cloud:PWMD:64
cloud:PWMD2:80
cloud:C0:9
cloud:PH:820
cloud:CEXP0:-12535
Loose/in: cexp:0:c:1797
cloud:PWMD:67
cloud:PWMD2:77
cloud:WL1:96
cloud:C0:53
cloud:CEXP0:-12491
Loose/in: cexp:0:c:1818
cloud:PWMD:69
cloud:PWMD2:75
cloud:WL1:97
cloud:C0:74
cloud:CEXP0:-12470
Loose/in: cexp:0:c:1828
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Roberto,

While I had the serial monitor, I wanted to see why it wouldn't auto connect back to the cloud server when power was removed. Does the inability to open the config file for saving have something to do with it?

Code: Select all

*WM: DIRECT-6C-HP ENVY 7640 series
*WM: -93
*WM: Sent config page
*WM: Request redirected to captive portal
*WM: Handle root
*WM: WiFi save
*WM: Parameter
*WM: Cloud Username
*WM: Loose
*WM: Parameter
*WM: Cloud Password
*WM: ##########
*WM: Sent wifi save page
*WM: Connecting to new AP
Checking Wifi Credentials
*WM: Connecting as wifi client...
*WM: Connection result: 
*WM: 3
Should save config
username: Loose
Start
saving config
failed to open config file for writing
{"mqtt_username":"Loose","mqtt_password":"#######"}
IP address: 192.168.1.22
Connecting to cloud server...
Connected
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

I can see that the hub is reading fine. It does report numbers around 1828.
There may be something wrong with the calibration process and storing that number into the memory.
Let me dig it up and see what I can find out.
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Good evening Roberto,

I tried doing all of the steps again and still have the two main issues.

1) Cloud wifi Hub will no longer auto-connect to cloud server if power is disconnected. I have to use a paper clip to enter setup mode.

2) Information from attached salinity module doesn't make sense.
- shows as 227 on android app
- RA* screen shows:
Attachments
RA Star custom0.jpg
RA Star custom0.jpg (35.99 KiB) Viewed 6529 times
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Load this code and send me the log.

Code: Select all

// Example: storing JSON configuration file in flash file system
//
// Uses ArduinoJson library by Benoit Blanchon.
// https://github.com/bblanchon/ArduinoJson
//
// Created Aug 10, 2015 by Ivan Grokhotkov.
//
// This example code is in the public domain.

#include <ArduinoJson.h>
#include "FS.h"

bool loadConfig() {
  File configFile = SPIFFS.open("/config.json", "r");
  if (!configFile) {
    Serial.println("Failed to open config file");
    return false;
  }

  size_t size = configFile.size();
  if (size > 1024) {
    Serial.println("Config file size is too large");
    return false;
  }

  // Allocate a buffer to store contents of the file.
  std::unique_ptr<char[]> buf(new char[size]);

  // We don't use String here because ArduinoJson library requires the input
  // buffer to be mutable. If you don't use ArduinoJson, you may as well
  // use configFile.readString instead.
  configFile.readBytes(buf.get(), size);

  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& json = jsonBuffer.parseObject(buf.get());

  if (!json.success()) {
    Serial.println("Failed to parse config file");
    return false;
  }

  const char* serverName = json["serverName"];
  const char* accessToken = json["accessToken"];

  // Real world application would store these values in some variables for
  // later use.

  Serial.print("Loaded serverName: ");
  Serial.println(serverName);
  Serial.print("Loaded accessToken: ");
  Serial.println(accessToken);
  return true;
}

bool saveConfig() {
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& json = jsonBuffer.createObject();
  json["serverName"] = "api.example.com";
  json["accessToken"] = "128du9as8du12eoue8da98h123ueh9h98";

  File configFile = SPIFFS.open("/config.json", "w");
  if (!configFile) {
    Serial.println("Failed to open config file for writing");
    return false;
  }

  json.printTo(configFile);
  return true;
}

void setup() {
  Serial.begin(57600);
  Serial.println("");
  delay(1000);
  Serial.println("Mounting FS...");

  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount file system");
    return;
  }


  if (!saveConfig()) {
    Serial.println("Failed to save config");
  } else {
    Serial.println("Config saved");
  }

  if (!loadConfig()) {
    Serial.println("Failed to load config");
  } else {
    Serial.println("Config loaded");
  }
}

void loop() {
}
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Log below:

Code: Select all

SDK:3.0.0-dev(c0f7b44)/Core:2.5.0=20500000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1/BearSSL:6778687

scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 

connected with K2GVR, channel 6
dhcp client start...
Mounting FS...
Failed to mount file system
ip:192.168.1.16,mask:255.255.255.0,gw:192.168.1.1
pm open,type:2 0
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Are you sure you loaded the code.
It is supposed to have a different log.
There is nothing related to wifi on that code.
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Yes but I guess I need to confirm something. I uploaded that code to the Cloud Wifi Hub. Was I supposed to upload it to the RA*?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Yes. Cloud hub.
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Once I uploaded the code to it the hub produced that output via the serial monitor and then went dark. As in, the light wasn't on at all, I had to upload the previous code that you posted to get it to respond again.

Side note, now the UAPP doesn't work for me now. I get 'Cloud server: Connecting...' with no information. I can see info using the portal once I login.
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

When you load the original code, does it produce the same log?
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

This is the monitor uploading the original code:

Code: Select all


SDK:3.0.0-dev(c0f7b44)/Core:2.5.0=20500000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1/BearSSL:6778687

Current version: 1.0.1
0 temperature probe(s) found
failed to mount FS
*WM: Adding parameter
*WM: Cloud Username
*WM: Adding parameter
*WM: Cloud Password
*WM: 
*WM: AutoConnect
*WM: Connecting as wifi client...
*WM: Using last saved values, should be faster
scandone
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 

connected with K2GVR, channel 6
dhcp client start...
ip:192.168.1.16,mask:255.255.255.0,gw:192.168.1.1
*WM: Connection result: 
*WM: 3
*WM: IP Address:
*WM: 192.168.1.16
username: 
Start
IP address: 192.168.1.16
Connecting to cloud server...
Failed, rc=5 try again in 30 seconds
bcn_timout,ap_probe_send_start
pm open,type:2 0
bcn_timout,ap_probe_send_start
bcn_timout,ap_probe_send_start
Connecting to cloud server...
Failed, rc=5 try again in 30 seconds

And this is what I get once I manually reset the Hub:

Code: Select all

add 1
aid 1
station: 74:c6:3b:ff:00:e3 join, AID = 1
*WM: Request redirected to captive portal
*WM: Handle root
*WM: Request redirected to captive portal
*WM: Request redirected to captive portal
*WM: Request redirected to captive portal
*WM: Handle root
*WM: Request redirected to captive portal
*WM: Request redirected to captive portal
*WM: Handle root
*WM: Handle root
scandone
*WM: Scan done
*WM: K2GVR
*WM: -44
*WM: spookynet
*WM: -82
*WM: NETGEAR51
*WM: -84
*WM: HP-Print-98-ENVY 120 series
*WM: -87
*WM: Fios-HYDFT
*WM: -88
*WM: DIRECT-90-HP ENVY Photo 7800
*WM: -90
*WM: Sent config page
*WM: Request redirected to captive portal
*WM: Request redirected to captive portal
*WM: Handle root
*WM: Request redirected to captive portal
*WM: WiFi save
*WM: Parameter
*WM: Cloud Username
*WM: Loose
*WM: Parameter
*WM: Cloud Password
*WM: ####### <--- modified
*WM: Sent wifi save page
*WM: Connecting to new AP
station: 74:c6:3b:ff:00:e3 leave, AID = 1
rm 1
bcn 0
del if1
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
bcn 0
del if1
mode : sta(5c:cf:7f:ff:6d:17)
Checking Wifi Credentials
*WM: Connecting as wifi client...
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 

connected with K2GVR, channel 6
dhcp client start...
ip:192.168.1.16,mask:255.255.255.0,gw:192.168.1.1
*WM: Connection result: 
*WM: 3
Should save config
username: Loose
Start
saving config
failed to open config file for writing
{"mqtt_username":"Loose","mqtt_password":"####### <--- modified"}
IP address: 192.168.1.16
Connecting to cloud server...
Connected
Subscribing to Loose/out/#
Loose/in: all:0
Loose/in: io:255
Loose/in: cexp:0::-1
cloud:ATOLOW:0
cloud:ATOHIGH:0
cloud:EM:137
cloud:EM1:22
cloud:REM:7
cloud:BID:4
cloud:AF:0
cloud:SF:0
cloud:PWMD:95
cloud:PWMA:100
cloud:PWMDO:255
cloud:PWMAO:255
cloud:R1:227
R1:227
cloud:ROFF1:255
ROFF1:255
cloud:RON1:0
RON1:0
cloud:R2:131
R2:131
cloud:ROFF2:255
ROFF2:255
cloud:RON2:0
RON2:0
cloud:R3:0
R3:0
cloud:ROFF3:255
ROFF3:255
cloud:RON3:0
RON3:0
cloud:R4:0
R4:0
cloud:ROFF4:255
ROFF4:255
cloud:RON4:0
RON4:0
cloud:R5:0
R5:0
cloud:ROFF5:255

rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Ok, let's try this again.
Load this code and send the log:

Code: Select all

#include <FS.h>   //Include File System Headers
 
const char* filename = "/samplefile.txt";
 
  
void setup() {
  delay(1000);
  Serial.begin(57600);
  Serial.println();
 
  //Initialize File System
  if(SPIFFS.begin())
  {
    Serial.println("SPIFFS Initialize....ok");
  }
  else
  {
    Serial.println("SPIFFS Initialization...failed");
  }
 
  //Format File System
  if(SPIFFS.format())
  {
    Serial.println("File System Formated");
  }
  else
  {
    Serial.println("File System Formatting Error");
  }
 
  //Create New File And Write Data to It
  //w=Write Open file for writing
  File f = SPIFFS.open(filename, "w");
  
  if (!f) {
    Serial.println("file open failed");
  }
  else
  {
      //Write data to file
      Serial.println("Writing Data to File");
      f.print("This is sample data which is written in file\n");
      f.close();  //Close file
  }
 
}
 
void loop() {
  int i;
  
  //Read File data
  File f = SPIFFS.open(filename, "r");
  
  if (!f) {
    Serial.println("file open failed");
  }
  else
  {
      Serial.println("Reading Data from File:");
      //Data from file
      for(i=0;i<f.size();i++) //Read upto complete file size
      {
        Serial.print((char)f.read());
      }
      f.close();  //Close file
      Serial.println("File Closed");
  }
  delay(5000);
}
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Uploaded and log:

Code: Select all

SDK:3.0.0-dev(c0f7b44)/Core:2.5.0=20500000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1/BearSSL:6778687

SPIFFS Initialization...failed
File System Formatting Error
file open failed
file open failed
ip:192.168.1.16,mask:255.255.255.0,gw:192.168.1.1
file open failed
pm open,type:2 0
file open failed
file open failed
file open failed
file open failed
file open failed
file open failed
file open failed

Hub has no lights and no other log entries except repeating "file open failed"
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Just to be sure, you are using Adafruit HUZZAH ESP8266 and you have flash size as 4M (3M SPIFFS), correct?
Your log does not match to mine.
Also, You are using Arduino (Reef Angel compilation) v.1.6.8, right?
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

I started from scrath with uninstalling and reinstalling Arduino.

Hub connects automatically again and from your latest code I get.

Code: Select all

GDÚQ…@@HdI•÷LÑ»ëCP@æïTWZµ•FÄTÖ…é`\‰dHŠ`H…Öj¡VpJ…ØõëdJÄÚã…ÌTQÕ÷ß…HµZÄfû`\‹AíIµBHÉT^¥…
SPIFFS Initialize....ok

rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Good. Making progress.
Now I have to figure out the calibration still. Hang tight.
Roberto.
User avatar
Loose
Posts: 90
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by Loose »

Roberto,

Any updates?
rimai
Posts: 12881
Joined: Fri Mar 18, 2011 6:47 pm

Re: 2nd Salinity module w/Cloud Wifi Hub

Post by rimai »

Ok, I got it working now.
Upload your RA* code through the webwizard to use the latest libraries changes I have made.
Then, upload this to your cloud wifi hub and calibrate.

Code: Select all

#include <FS.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266httpUpdate.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
#include <Wire.h>
#include <OneWire.h>
#include <CloudGlobals.h>

// ***********************************************************************
// Change fallback ports below
// Fallback ports will be turned on when cloud connection is lost
// Add each port separated by a |
// For example, if you would like for port 1 and port 5 of Relay Box 1 to be turned on when cloud connection is lost,
// you should add Port1Bit | Port5Bit
// It would look like this:
// #define Relay1FallBack Port1Bit | Port5Bit

#define Relay1FallBack 0
#define Relay2FallBack 0
#define Relay3FallBack 0
#define Relay4FallBack 0
#define Relay5FallBack 0
#define Relay6FallBack 0
#define Relay7FallBack 0
#define Relay8FallBack 0

// Redirect expansion modules to another custom expansion field.
// This is only required if you have multiple modules of the same parameter.
// For example, if you have one Cloud module with an existing salinity module already and wants to add another Cloud module
// with anoter salinity module and report those readings as a Custom Expansion Module 1
// In this case you have to change the CloudCustomModule1 to CUSTOM_SALINITY.
// The values that can be entered are:
// CUSTOM_NONE  0
// CUSTOM_SALINITY  1
// CUSTOM_ORP 2
// CUSTOM_PHEXP 3
// CUSTOM_WL  4
// CUSTOM_MULTI_WL1 5
// CUSTOM_MULTI_WL2 6
// CUSTOM_MULTI_WL3 7
// CUSTOM_MULTI_WL4 8

#define CloudCustomModule1  CUSTOM_NONE
#define CloudCustomModule2  CUSTOM_NONE
#define CloudCustomModule3  CUSTOM_NONE
#define CloudCustomModule4  CUSTOM_NONE
#define CloudCustomModule5  CUSTOM_NONE
#define CloudCustomModule6  CUSTOM_NONE
#define CloudCustomModule7  CUSTOM_NONE
#define CloudCustomModule8  CUSTOM_NONE

// Assign Temperature probes ID
// Only assign temperature probes IDs that you currently are not using in the head unit.
// If you have a total of more than 3 probes, make sure to add the following line on the setup section of the head unit code:
// ReefAngel.AddExtraTempProbes();
// For example, if you only have 1 probe connected to the head unit, assign IDs 2 and 3.
// If you have 2 probes in the head unit and 2 probes in the Cloud Wifi Hub, you must add the above line and you would assign
// IDs 3 and 4.
// Assign ID 0 to unused probes in the Hub.

byte TempProbeIDs[] = {4, 5};

// Do not change anything below
// ***********************************************************************
// solid green - factory reset
// blink green - connecting wifi
// blink blue - configuration required (SoftAP)
// blink magenta - connecting to cloud server
// solid cyan - connected to cloud server
// blinking cyan - transmitting/receiving data
// solid yellow - firmware update

#define LED_GREEN 2
#define LED_BLUE 0
#define LED_RED 16
#define RESET_ALL A0
#define INPUT1  12
#define INPUT2  13
#define TEMP_PIN  14

#define version "1.0.1"

#define MQTTServer "cloud.reefangel.com"

#define MQTTPORT 1883 // MQTT server port

WiFiManager wifiManager;
WiFiClient espClient;
PubSubClient CloudClient(espClient);
Ticker ticker;
OneWire ds(TEMP_PIN);

byte data[2];
byte addr[8];
byte addr1[8];
byte addr2[8];

boolean first_connection = true;
boolean shouldSaveConfig = false;
boolean updating = false;

unsigned long cloudmillis = millis();
unsigned long client_timeout = millis();
unsigned long serial_timeout = millis();

String currentLine = "";                // make a String to hold incoming data from the client

char mqtt_username[32];
char mqtt_password[32];

void APtick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void Wifitick()
{
  //toggle state
  int state = digitalRead(LED_GREEN);  // get the current state of GPIO1 pin
  digitalWrite(LED_GREEN, !state);     // set pin to the opposite state
}

void Cloudtick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_RED, !state);     // set pin to the opposite state
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void Datatick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_GREEN, !state);     // set pin to the opposite state
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void LED_Color(int Red, int Green, int Blue)
{
  analogWrite(LED_RED, 1023 - Red);
  analogWrite(LED_GREEN, 1023 - Green);
  analogWrite(LED_BLUE, 1023 - Blue);
}

int memory_read_int(int address)
{
  int temp=0;
  temp=EEPROM.read(address)<<8;
  temp+=EEPROM.read(address+1);
  return temp;
}

void memory_write_int(int address, const int data)
{
  if (memory_read_int(address) != data)
  {
    EEPROM.write(address,data>>8);
    EEPROM.write(address+1,data&0xff);
    EEPROM.commit();
  }
}

unsigned int crc16(int *ptr, byte len)
{
  unsigned int crc = 0xFFFF;
  byte i;
  byte temp = 0;
  int test;
  while (len--)
  {
    crc ^= *ptr++;
    for (i = 0; i < 8; i++)
    {
      if (crc & 0x01)
      {
        crc >>= 1;
        crc ^= 0xA001;
      }
      else
      {
        crc >>= 1;
      }
    }
  }
  return crc;
}

void blink_data_led(byte timer)
{
  digitalWrite(LED_RED, LOW);
  delay(timer);
  digitalWrite(LED_RED, HIGH);
}

void Publish(char* pub_buffer, char* buffer)
{
  CloudClient.publish(pub_buffer, buffer);
  Serial.print(pub_buffer);
  Serial.print(": ");
  Serial.println(buffer);
  blink_data_led(50);
}

void reconnect() {
  // Loop until we're reconnected
  if (!CloudClient.connected()) {
    cloudmillis = millis();
    //    Serial.print(F("Username: "));
    //    Serial.println(CLOUD_USERNAME);
    Serial.println("Connecting to cloud server...");
    // Attempt to connect
    //Serial.println(sub_buffer);
    if (CloudClient.connect(clientid, mqtt_username, mqtt_password)) {
      Serial.println("Connected");
      // Once connected, publish an announcement...
      Serial.print("Subscribing to ");
      Serial.println(sub_buffer);
      CloudClient.subscribe(sub_buffer);
      Publish(pub_buffer, "all:0");
      ticker.detach();
      LED_Color(0, 1023, 1023);

      //Serial.swap();
    } else {
      Serial.print("Failed, rc=");
      Serial.print(CloudClient.state());
      Serial.println(" try again in 30 seconds");
    }
  }
}

void ApplyCalibration(byte module, byte type)
{
  CustomExpansion[module - 1] = type;
  switch (type)
  {
    case CUSTOM_SALINITY:
      sprintf(pub_salinity, "cexp:%d:", module - 1);
      break;
    case CUSTOM_ORP:
      sprintf(pub_orp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_PHEXP:
      sprintf(pub_phexp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_WL:
      sprintf(pub_wl, "cexp:%d:", module - 1);
      sprintf(pub_custom_wl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_MULTI_WL1:
    case CUSTOM_MULTI_WL2:
    case CUSTOM_MULTI_WL3:
    case CUSTOM_MULTI_WL4:
      sprintf(pub_multiwl, "cexp:%d:", module - 1);
      sprintf(pub_custom_multiwl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_NONE:
      break;
  }
}

void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void configModeCallback (WiFiManager *myWiFiManager) {
  LED_Color(0, 0, 0);
  ticker.detach();
  Serial.println("Entered config mode");
  WiFi.softAPIP();
  ticker.attach(0.5, APtick);
}

void WifiCheckCallback () {
  WiFi.softAPdisconnect(true);
  LED_Color(0, 0, 0);
  ticker.detach();
  Serial.println("Checking Wifi Credentials");
  ticker.attach(0.5, Wifitick);
}

void callback(char* topic, byte* payload, unsigned int length) {

  boolean data_found = false;
  int payload_data = 0;
  byte data_index = 0;

  Serial.print("cloud:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'F' && payload[3] == 'F' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0' - 1;
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOffE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'N' && payload[4] == ':')
  {
    data_found = true;
    data_index = payload[3] - '0' - 1;
    for (byte a = 5; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOnE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[2] == ':')
  {
    data_found = true;
    data_index = payload[1] - '0' - 1;
    for (byte a = 3; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayDataE[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannel[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == 'O' && payload[6] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 7; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannelOverride[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == '1' && payload[4] == '6' && payload[5] == 'E' && payload[8] == ':')
  {
    data_found = true;
    data_index = (payload[6] - '0') * 10;
    data_index += (payload[7] - '0');
    for (byte a = 9; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    Expansion16Channel[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == '1' && payload[4] == '6' && payload[5] == 'E' && payload[6] == 'O' && payload[9] == ':')
  {
    data_found = true;
    data_index = (payload[7] - '0') * 10;
    data_index += (payload[8] - '0');
    for (byte a = 10; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    Expansion16ChannelOverride[data_index] = payload_data;
  }
  else if (payload[0] == 'O' && payload[1] == 'R' && payload[2] == 'P' && payload[3] == 'C' && payload[4] == ':' && ORPFound)
  {
    Serial.println(F("ORP calibration"));
    data_found = true;
    if (payload[5] == '0')
      ORPCal = false;
    else if (payload[5] == '1')
      ORPCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_ORPMin, CalVal1);
      memory_write_int(Mem_I_ORPMax, payload_data);
      ORPMin = CalVal1;
      ORPMax = payload_data;
      ORPCal = false;
    }
  }
  else if (payload[0] == 'S' && payload[1] == 'A' && payload[2] == 'L' && payload[3] == 'C' && payload[4] == ':' && SalinityFound)
  {
    Serial.println(F("Sal calibration"));
    data_found = true;
    if (payload[5] == '0')
      SalCal = false;
    else if (payload[5] == '1')
      SalCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_SalMax, payload_data);
      SalMax = payload_data;
      SalCal = false;
    }
  }
  else if (payload[0] == 'P' && payload[1] == 'H' && payload[2] == 'E' && payload[3] == 'C' && payload[4] == ':' && PHExpFound)
  {
    Serial.println(F("PH Exp calibration"));
    data_found = true;
    if (payload[5] == '0')
      PHExpCal = false;
    else if (payload[5] == '1')
      PHExpCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_PHExpMin, CalVal1);
      memory_write_int(Mem_I_PHExpMax, payload_data);
      PHExpMin = CalVal1;
      PHExpMax = payload_data;
      PHExpCal = false;
    }
  }
  else if (payload[0] == 'W' && payload[1] == 'L' && payload[3] == 'C' && payload[4] == ':' && (WLFound || MultiWLFound))
  {
    Serial.println(F("WL calibration"));
    data_found = true;
    data_index = payload[2] - '0';
    if (payload[5] == '0')
      WLCal[data_index] = false;
    else if (payload[5] == '1')
    {
      if (data_index == 0 && WLFound)
        WLCal[data_index] = true;
      if (data_index > 0 && MultiWLFound)
        WLCal[data_index] = true;
    }
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      if (data_index == 0)
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
      }
      if (data_index > 0 && data_index < 5)
      {
        memory_write_int(Mem_I_WaterLevel1Min + (data_index * 2) - 2, CalVal1);
        memory_write_int(Mem_I_WaterLevel1Max + (data_index * 2) - 2, payload_data);
      }
      WLMin[data_index] = CalVal1;
      WLMax[data_index] = payload_data;
      WLCal[data_index] = false;
    }
  }
  else if (payload[0] == 'C' && payload[1] == 'E' && payload[2] == 'X' && payload[3] == 'P' && payload[5] == 'C' && payload[6] == ':')
  {
    Serial.println(F("Custom Exp calibration"));
    data_found = true;
    data_index = payload[4] - '0';
    if (payload[7] == '0')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = false;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = false;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = false;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = false;
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] >= CUSTOM_MULTI_WL1 && CustomExpansion[data_index] <= CUSTOM_MULTI_WL4) WLCal[a] = false;
    }
    else if (payload[7] == '1')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = true;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = true;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = true;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL1) WLCal[1] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL2) WLCal[2] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL3) WLCal[3] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL4) WLCal[4] = true;
    }
    else if (payload[7] == '2')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      CalVal1 = payload_data;
    }
    else if (payload[7] == '3')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      if (pub_salinity[0] == 'c')
      {
        memory_write_int(Mem_I_SalMax, payload_data);
        SalMax = payload_data;
        SalCal = false;
      }
      if (pub_orp[0] == 'c')
      {
        memory_write_int(Mem_I_ORPMin, CalVal1);
        memory_write_int(Mem_I_ORPMax, payload_data);
        ORPMin = CalVal1;
        ORPMax = payload_data;
        ORPCal = false;
      }
      if (pub_phexp[0] == 'c')
      {
        memory_write_int(Mem_I_PHExpMin, CalVal1);
        memory_write_int(Mem_I_PHExpMax, payload_data);
        PHExpMin = CalVal1;
        PHExpMax = payload_data;
        PHExpCal = false;
      }
      if (pub_wl[0] == 'c')
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
        WLMin[0] = CalVal1;
        WLMax[0] = payload_data;
        WLCal[0] = false;
      }
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && WLCal[a] == true)
        {
          memory_write_int(Mem_I_WaterLevel1Min + (a * 2) - 2, CalVal1);
          memory_write_int(Mem_I_WaterLevel1Max + (a * 2) - 2, payload_data);
          WLMin[a] = CalVal1;
          WLMax[a] = payload_data;
          WLCal[a] = false;
        }
    }
  }
  if (data_found)
  {
    blink_data_led(30);
    for (int a = 0; a < length; a++)
      Serial.write(payload[a]);
    Serial.println();
  }
}

void setup() {
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(INPUT1, INPUT_PULLUP);
  pinMode(INPUT2, INPUT_PULLUP);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_BLUE, HIGH);
  digitalWrite(LED_RED, HIGH);
  randomSeed(analogRead(0));
  wifi_station_set_hostname( "ReefAngelCloudHub" );
  Serial.begin(57600);
  Serial.setRxBufferSize(2048);
  EEPROM.begin(512);
  Wire.begin();

  wifiManager.setDebugOutput(true);

  Serial.println("");
  Serial.print("Current version: ");
  Serial.println(version);

  SalinityFound = false;
  ORPFound = false;
  PHExpFound = false;
  WLFound = false;
  MultiWLFound = false;
  HumidityFound = false;

  sprintf(pub_salinity, "sal");
  sprintf(pub_orp, "orp");
  sprintf(pub_phexp, "phe");
  sprintf(pub_wl, "wl");
  sprintf(pub_multiwl, "wl");
  sprintf(pub_humidity, "hum");

  // Temperature
  byte count = 0;
  while (ds.search(addr))
  {
    if (addr[0] == 0x28)
    {
      count++;
      if (count == 1) memcpy(addr1, addr, 8);
      if (count == 2) memcpy(addr2, addr, 8);
    }
  }
  ds.reset_search();
  Serial.print(count);
  Serial.println(" temperature probe(s) found");

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    RelayDataE[EID] = 0;
    RelayMaskOnE[EID] = 0;
    RelayMaskOffE[EID] = 0xff;
  }
  RelayFallBackE[0] = Relay1FallBack;
  RelayFallBackE[1] = Relay2FallBack;
  RelayFallBackE[2] = Relay3FallBack;
  RelayFallBackE[3] = Relay4FallBack;
  RelayFallBackE[4] = Relay5FallBack;
  RelayFallBackE[5] = Relay6FallBack;
  RelayFallBackE[6] = Relay7FallBack;
  RelayFallBackE[7] = Relay8FallBack;

  // Dimming
  lastcrc = -1;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    ExpansionChannel[a] = 0;
    ExpansionChannelOverride[a] = 255;
  }

  // 16 Channel Dimming
  lastcrc16 = -1;
  for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
  {
    Expansion16Channel[a] = 0;
    Expansion16ChannelOverride[a] = 255;
  }

  // IO
  Params.IO = 63;
  OldParams.IO = 63;

  // Leak
  Params.Leak = 0;
  OldParams.Leak = 0;

  // ORP
  Params.ORP = 0;
  OldParams.ORP = 0;
  ORPCal = false;
  ORPMin = memory_read_int(Mem_I_ORPMin);
  if (ORPMin == 65535) ORPMin = 0;
  ORPMax = memory_read_int(Mem_I_ORPMax);

  // Salinity
  Params.Salinity = 0;
  OldParams.Salinity = 0;
  SalCal = false;
  SalMax = memory_read_int(Mem_I_SalMax);

  // pH Exp
  Params.PHExp = 0;
  OldParams.PHExp = 0;
  PHExpCal = false;
  PHExpMin = memory_read_int(Mem_I_PHExpMin);
  if (PHExpMin == 65535) PHExpMin = 0;
  PHExpMax = memory_read_int(Mem_I_PHExpMax);

  // Humidity
  Params.Humidity = 0;
  OldParams.Humidity = 0;

  // Water Level
  for (int a = 0; a < WL_CHANNELS; a++)
  {
    Params.WL[a] = 0;
    OldParams.WL[a] = 0;
    WLCal[a] = false;
  }
  WLMin[0] = memory_read_int(Mem_I_WaterLevelMin);
  WLMax[0] = memory_read_int(Mem_I_WaterLevelMax);
  WLMin[1] = memory_read_int(Mem_I_WaterLevel1Min);
  WLMax[1] = memory_read_int(Mem_I_WaterLevel1Max);
  WLMin[2] = memory_read_int(Mem_I_WaterLevel2Min);
  WLMax[2] = memory_read_int(Mem_I_WaterLevel2Max);
  WLMin[3] = memory_read_int(Mem_I_WaterLevel3Min);
  WLMax[3] = memory_read_int(Mem_I_WaterLevel3Max);
  WLMin[4] = memory_read_int(Mem_I_WaterLevel4Min);
  WLMax[4] = memory_read_int(Mem_I_WaterLevel4Max);

  for (int a = 0; a < 5; a++)
  {
    if (WLMin[a] == 65535) WLMin[a] = 0;
  }
  ApplyCalibration(1, CloudCustomModule1);
  ApplyCalibration(2, CloudCustomModule2);
  ApplyCalibration(3, CloudCustomModule3);
  ApplyCalibration(4, CloudCustomModule4);
  ApplyCalibration(5, CloudCustomModule5);
  ApplyCalibration(6, CloudCustomModule6);
  ApplyCalibration(7, CloudCustomModule7);
  ApplyCalibration(8, CloudCustomModule8);

  if (analogRead(RESET_ALL) < 50)
  {
    //    updating=true;
    Serial.println("Resetting");
    EEPROM.write(128, 0);
    EEPROM.commit();
    ESP.reset();
    while (1);
  }

  wifiManager.setVersion(version);
  if (EEPROM.read(128) != 1)
  {
    wifiManager.resetSettings();
    SPIFFS.format();
    EEPROM.write(128, 1);
    EEPROM.commit();
  }

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(mqtt_username, json["mqtt_username"]);
          strcpy(mqtt_password, json["mqtt_password"]);

        } else {
          Serial.println("failed to load json config");
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }

  WiFiManagerParameter custom_mqtt_username("Cloud Username", "Cloud Username", mqtt_username, 40);
  WiFiManagerParameter custom_mqtt_password("Cloud Password", "Cloud Password", mqtt_password, 40);
  wifiManager.addParameter(&custom_mqtt_username);
  wifiManager.addParameter(&custom_mqtt_password);
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  wifiManager.setAPCallback(configModeCallback);
  wifiManager.setCheckWifiCallback(WifiCheckCallback);

  LED_Color(0, 0, 0);
  ticker.attach(0.5, Wifitick);
  wifiManager.autoConnect("ReefAngelCloudHub");
  ticker.detach();
  LED_Color(900, 0, 1023);

  CloudClient.setServer(MQTTServer, MQTTPORT);
  CloudClient.setCallback(callback);

  strcpy(mqtt_username, custom_mqtt_username.getValue());
  strcpy(mqtt_password, custom_mqtt_password.getValue());
  Serial.print("username: ");
  Serial.println(mqtt_username);
  //  Serial.print("password: ");
  //  Serial.println(mqtt_password);
  sprintf(clientid, "%s%02d", mqtt_username, random(10000));
  sprintf(pub_buffer, "%s/in", mqtt_username);
  sprintf(sub_buffer, "%s/out/#", mqtt_username);
  Serial.println("Start");

  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_username"] = mqtt_username;
    json["mqtt_password"] = mqtt_password;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    json.printTo(Serial);
    Serial.println("");
    json.printTo(configFile);
    configFile.close();
    //end save
  }

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  if ((analogRead(RESET_ALL) < 50) && !updating)
  {
    if (WiFi.status() == WL_CONNECTED)
    {
      updating = true;
      ticker.detach();
      LED_Color(1023, 900, 0);
      Serial.println("Updating...");
      ESPhttpUpdate.update("forum.reefangel.com", 80, "/firmware/CloudWifiESP8266Hub.ino.bin");
    }
    else
    {
      Serial.println("Resetting");
      EEPROM.write(128, 0);
      EEPROM.commit();
      ESP.reset();
      while (1);
    }
  }
  if (!CloudClient.connected() && (((millis() - cloudmillis) > 30000) || first_connection)) {
    first_connection = false;
    LED_Color(0, 0, 0);
    ticker.detach();
    ticker.attach(0.5, Cloudtick);
    reconnect();
  }
  CloudClient.loop();

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    byte TempRelay = RelayDataE[EID];
    TempRelay &= RelayMaskOffE[EID];
    TempRelay |= RelayMaskOnE[EID];
    if (!CloudClient.connected())
      TempRelay = RelayFallBackE[EID];
    Wire.beginTransmission(I2CExpModule + EID);
    Wire.write(~TempRelay);  // MSB
    Wire.endTransmission();
  }

  // Dimming
  byte thiscrc = 0;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    thiscrc += ExpansionChannel[a] * (a + 1);
    thiscrc += ExpansionChannelOverride[a] * (a + 1);
  }
  if (millis() % 60000 < 200) lastcrc = -1;
  if (lastcrc != thiscrc || millis() < 5000)
  {
    lastcrc = thiscrc;
    // setup PCA9685 for data receive
    // we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
    Wire.beginTransmission(I2CPWM_PCA9685);
    Wire.write((uint8_t)0);
    Wire.write(0xa1);
    Wire.endTransmission();
    for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
    {
      int data;
      if (ExpansionChannelOverride[a] <= 100)
        data = ExpansionChannelOverride[a] * 40.96;
      else
        data = ExpansionChannel[a] * 40.96;
      Wire.beginTransmission(I2CPWM_PCA9685);
      Wire.write(0x8 + (4 * a));
      Wire.write(data & 0xff);
      Wire.write(data >> 8);
      Wire.endTransmission();
    }
  }

  // 16 Channel Dimming
  int thiscrc16 = 0;
  for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
  {
    thiscrc16 += Expansion16Channel[a] * (a + 1);
    thiscrc16 += Expansion16ChannelOverride[a] * (a + 1);
  }
  if (millis() % 60000 < 200) lastcrc16 = -1;
  if (lastcrc16 != thiscrc16 || millis() < 5000)
  {
    lastcrc16 = thiscrc16;
    // setup PCA9685 for data receive
    // we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
    Wire.beginTransmission(I2CPWM_16CH_PCA9685);
    Wire.write((uint8_t)0);
    Wire.write(0xa1);
    Wire.endTransmission();
    for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
    {
      int data;
      if (Expansion16ChannelOverride[a] <= 100)
        data = Expansion16ChannelOverride[a];
      else
        data = Expansion16Channel[a];
      Wire.beginTransmission(I2CPWM_16CH_PCA9685);
      Wire.write(0x8 + (4 * a));
      Wire.write(data & 0xff);
      Wire.write(data >> 8);
      Wire.endTransmission();
    }
  }

  if (CloudClient.connected())
  {
    // IO
    Params.IO = 63;
    Wire.requestFrom(I2CIO_PCF8574, 1);
    if (Wire.available())
      Params.IO = Wire.read();
    if (digitalRead(INPUT1) == HIGH) Params.IO += 64;
    if (digitalRead(INPUT2) == HIGH) Params.IO += 128;
    if (Params.IO != OldParams.IO)
    {
      OldParams.IO = Params.IO;
      sprintf(buffer, "io:%d", Params.IO);
      Publish(pub_buffer, buffer);
    }

    // Leak
    int iLeak = 0;
    Wire.requestFrom(I2CLeak, 2);
    if (Wire.available())
    {
      iLeak = Wire.read();
      iLeak = iLeak << 8;
      iLeak += Wire.read();
      Params.Leak = iLeak > 2000;
    }
    if (Params.Leak != OldParams.Leak)
    {
      OldParams.Leak = Params.Leak;
      sprintf(buffer, "leak:%d", Params.Leak);
      Publish(pub_buffer, buffer);
    }

    if (millis() - Paramsmillis > 1000)
    {
      Paramsmillis = millis();

      // Temperature
      if (addr1[0] != 0)
      {
        ds.reset();
        ds.select(addr1);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[1] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[1] = Params.Temp[1] / 1.6;
        if (Params.Temp[1] == 0) Params.Temp[1] = 0;
        if (Params.Temp[1] > 850) Params.Temp[1] = 0;
        Params.Temp[1] = Params.Temp[1] * 1.8 + 320;
        if (Params.Temp[1] != OldParams.Temp[1])
        {
          OldParams.Temp[1] = Params.Temp[1];
          sprintf(buffer, "t:%d:%d", TempProbeIDs[0], Params.Temp[1]);
          if (TempProbeIDs[0] != 0) Publish(pub_buffer, buffer);
        }
      }
      if (addr2[0] != 0)
      {
        ds.reset();
        ds.select(addr2);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[2] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[2] = Params.Temp[2] / 1.6;
        if (Params.Temp[2] == 0) Params.Temp[2] = 0;
        if (Params.Temp[2] > 850) Params.Temp[2] = 0;
        Params.Temp[2] = Params.Temp[2] * 1.8 + 320;
        if (Params.Temp[2] != OldParams.Temp[2])
        {
          OldParams.Temp[2] = Params.Temp[2];
          sprintf(buffer, "t:%d:%d", TempProbeIDs[1], Params.Temp[2]);
          if (TempProbeIDs[1] != 0) Publish(pub_buffer, buffer);
        }
      }

      // ORP
      unsigned long temporp = 0;
      int iORP = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CORP, 2);
        if (Wire.available())
        {
          iORP = Wire.read();
          iORP = iORP << 8;
          iORP += Wire.read();
        }
        temporp += iORP;
      }
      temporp = temporp / 20;
      if (temporp != 0)
      {
        Params.ORP = map(temporp, ORPMin, ORPMax, 0, 470); // apply the calibration to the sensor reading
        Params.ORP = constrain(Params.ORP, 0, 550);
        if (pub_orp[0] == 'o') ORPFound = true;
      }
      if (ORPCal)
      {
        if (pub_orp[0] == 'o') sprintf(buffer, "%sc:%d", pub_orp, temporp);
        if (pub_orp[0] == 'c')
        {
          sprintf(buffer, "cexpc:%c:%d", pub_orp[5], temporp);
        }
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.ORP != OldParams.ORP)
        {
          OldParams.ORP = Params.ORP;
          sprintf(buffer, "%s:%d", pub_orp, Params.ORP);
          Publish(pub_buffer, buffer);
        }
      }

      // Salinity
      unsigned long tempsal = 0;
      int iSAL = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CSalinity, 2);
        if (Wire.available())
        {
          iSAL = Wire.read();
          iSAL = iSAL << 8;
          iSAL += Wire.read();
        }
        tempsal += iSAL;
      }
      tempsal = tempsal / 20;
      if (tempsal != 0)
      {
        Params.Salinity = map(tempsal, 0, SalMax, 60, 350); // apply the calibration to the sensor reading
        if (pub_salinity[0] == 's') SalinityFound = true;
      }
      if (SalCal)
      {
        if (pub_salinity[0] == 's') sprintf(buffer, "%sc:%d", pub_salinity, tempsal);
        if (pub_salinity[0] == 'c')
        {
          sprintf(buffer, "cexpc:%c:%d", pub_salinity[5], tempsal);
        }
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.Salinity != OldParams.Salinity)
        {
          OldParams.Salinity = Params.Salinity;
          sprintf(buffer, "%s:%d", pub_salinity, Params.Salinity);
          Publish(pub_buffer, buffer);
        }
      }

      // pH Exp
      unsigned long tempphexp = 0;
      int iPHExp = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPH, 2);
        if (Wire.available())
        {
          iPHExp = Wire.read();
          iPHExp = iPHExp << 8;
          iPHExp += Wire.read();
        }
        tempphexp += iPHExp;
      }
      tempphexp = tempphexp / 20;
      if (tempphexp != 0)
      {
        Params.PHExp = map(tempphexp, PHExpMin, PHExpMax, 700, 1000); // apply the calibration to the sensor reading
        Params.PHExp = constrain(Params.PHExp, 100, 1400);
        if (pub_phexp[0] == 'p') PHExpFound = true;
      }
      if (PHExpCal)
      {
        if (pub_orp[0] == 'p') sprintf(buffer, "%sc:%d", pub_phexp, tempphexp);
        if (pub_orp[0] == 'c')
        {
          sprintf(buffer, "cexpc:%c:%d", pub_phexp[5], tempphexp);
        }
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.PHExp != OldParams.PHExp)
        {
          OldParams.PHExp = Params.PHExp;
          sprintf(buffer, "%s:%d", pub_phexp, Params.PHExp);
          Publish(pub_buffer, buffer);
        }
      }

      // PAR
      unsigned long temppar = 0;
      int iPAR = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPAR, 2);
        if (Wire.available())
        {
          iPAR = Wire.read();
          iPAR = iPAR << 8;
          iPAR += Wire.read();
        }
        temppar += iPAR;
      }
      temppar = temppar / 20;
      if (temppar != 0)
      {
        temppar *= 5000; // apply the calibration to the sensor reading
        temppar /= 8192;
        Params.PAR = temppar;
      }
      if (Params.PAR != OldParams.PAR)
      {
        OldParams.PAR = Params.PAR;
        sprintf(buffer, "par:%d", Params.PAR);
        Publish(pub_buffer, buffer);
      }

      // Humidity
      int iHumidity = 0;
      int reply[10];

      Wire.beginTransmission(I2CHumidity);
      Wire.endTransmission();  // For some reason, it needs this to work??? Bug with sensor??
      Wire.beginTransmission(I2CHumidity);
      Wire.write(0x3); // 0x3 for read 0x10 for write to registers
      Wire.write((byte)0x0);  // start at address 0x0 for humidity
      Wire.write(2);  // request 2 bytes data for humidity or 4 bytes for temperature+humidity
      Wire.endTransmission();

      Wire.requestFrom(I2CHumidity, 6); // Request 6 bytes
      for (int i = 0; i < 6; i++)
        if (Wire.available()) reply[i] = Wire.read();
      if (reply[0] == 0x3 && reply[1] == 0x2) // The response need to contain function (0x3) and length of data (0x2)
      {
        int crc = reply[5];
        crc <<= 8;
        crc += reply[4];
        if (crc == crc16(reply, 4))
        {
          iHumidity = reply[2];
          iHumidity <<= 8;
          iHumidity += reply[3];
        }
      }
      Params.Humidity = iHumidity;
      if (Params.Humidity != OldParams.Humidity)
      {
        OldParams.Humidity = Params.Humidity;
        sprintf(buffer, "hum:%d", Params.Humidity);
        Publish(pub_buffer, buffer);
      }

      // Water Level
      for (int i = 0; i < WL_CHANNELS; i++)
      {
        unsigned long tempwl = 0;
        int iWL = 0;
        for (int a = 0; a < 20; a++)
        {
          if (i == 0)
          {
            Wire.requestFrom(I2CWaterLevel, 2);
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL;
            if (tempwl != 0 && pub_wl[0] == 'w') WLFound = true;
          }
          else
          {
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write(1); // Config Pointer
            byte addr = (0xb + i) << 4; // Select which channel to read
            addr += 0x03; // Programmable Gain
            Wire.write(addr);
            Wire.write(0x83);
            Wire.endTransmission();
            delay(10); // It takes 10ms for conversion to be completed
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write((uint8_t)0); // Convert Pointer
            Wire.endTransmission();
            Wire.requestFrom(I2CMultiWaterLevel, 2); // Request converted value
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL >> 4;
            if (tempwl != 0 && pub_multiwl[0] == 'w') MultiWLFound = true;
          }
        }
        tempwl = tempwl / 20;
        if (tempwl != 0)
        {
          Params.WL[i] = map(tempwl, WLMin[i], WLMax[i], 0, 100); // apply the calibration to the sensor reading
          Params.WL[i] = constrain(Params.WL[i], 0, 255);
        }
        if (WLCal[i])
        {
          if (i == 0)
          {
            if (pub_wl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_wl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_wl, tempwl);
          }
          else
          {
            if (pub_multiwl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_multiwl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_multiwl, tempwl);
          }
          Publish(pub_buffer, buffer);
        }
        else
        {
          if (Params.WL[i] != OldParams.WL[i])
          {
            OldParams.WL[i] = Params.WL[i];
            if (i == 0)
            {
              if (pub_wl[0] == 'c')
                sprintf(buffer, "%s%d", pub_wl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_wl, i, Params.WL[i]);
            }
            else
            {
              if (pub_multiwl[0] == 'c')
                sprintf(buffer, "%s%d", pub_multiwl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_multiwl, i, Params.WL[i]);
            }
            Publish(pub_buffer, buffer);
          }
        }
      }
      ds.reset();
      ds.select(addr1);
      ds.write(0x44, 0);
      ds.reset();
      ds.select(addr2);
      ds.write(0x44, 0);
    }
  }
}
Roberto.
Post Reply