Termostat

User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Czy to normalne że po kilkukrotnym odłączeniu napięcia układ z termostatem stracił dane do wifi, adres serwa i email? Musiałem go na nowo zarejestrować i skonfigurować wszystko od nowa. :(. Wykresy poszły się...
Screenshot_2024-11-13-11-32-32-13_40deb401b9ffe8e1df2f1cc5ba480b12.jpg
You do not have the required permissions to view the files attached to this post.
User avatar
pzygmunt
Posts: 20302
Joined: Tue Jan 19, 2016 9:26 am
Location: Paczków
Been thanked: 59 times

Post

Zdecydowanie nie jest to normalne.
SUPLA.... Nareszcie w domu.
User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Mam nazwijmy to nadrzędny przekaźnik 230V którym odcinam globalnie zasilanie od wszystkiego co steruje ogrzewaniem. Robiłem taki "wieloklik" co parenaście sekund i po którymś razie zauważyłem ten bubel. Dodam że pomiędzy klikaniami zmieniałem wartości temperatur na termostacie i nagle zrobił się offline. Ale o tym że na każdym z kanałów ma być nastawa górna to pamiętał, mimo że nie mam tego na sztywno w sofcie zadeklarowanego.


Mój program:

Code: Select all

/*
   Copyright (C) AC SOFTWARE SP. Z O.O

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   */

#define MAX_SLEEP_TIME_SEC 240

#ifdef ARDUINO_ARCH_AVR
#error "This example is not supported on Arduino AVR"
#endif

#include <SuplaDevice.h>
#include <supla/storage/eeprom.h>
#include <supla/network/esp_wifi.h>
#include <supla/device/status_led.h>
#include <supla/storage/littlefs_config.h>

#include <supla/network/esp_web_server.h>
#include <supla/network/html/device_info.h>
#include <supla/network/html/protocol_parameters.h>
#include <supla/network/html/status_led_parameters.h>
#include <supla/network/html/wifi_parameters.h>
#include <supla/device/supla_ca_cert.h>
#include <supla/control/hvac_base.h>
#include <supla/clock/clock.h>
#include <supla/network/html/time_parameters.h>
#include <supla/network/html/hvac_parameters.h>
#include <supla/control/internal_pin_output.h>
#include <supla/events.h>
#include <supla/actions.h>
#include <supla/sensor/virtual_thermometer.h>
#include <supla/control/button.h>
#include <supla/sensor/general_purpose_measurement.h>
#include <HTTPUpdateServer.h>

#include <ArduinoJson.h> //by Benoit Blanchon 6.17.0
#include <WiFiUdp.h>
String udp_msg;
#define udpPort 4210
char incomingPacket[255];  // buffer for incoming packets
WiFiUDP udp;
String msg;
word wykonaj_raz;

float temp_aktualna[17];
String channel_name[17];
byte grzanie[17];
unsigned long temp_aktualna_unsigned_long;
word temp_aktualna_word[17];
word timeout;
bool pierwsza_transmisja_UDP;

int state_output_[17];
int state_output_old_[17];

bool nowe_dane_udp_do_wyslania;

byte sekundy_od_ostatniej_transmisji_UDP_TX;
byte numer_kanalu_do_wyslania_przez_UDP;
unsigned long previousMillis_UDP;
unsigned long previousMillis_UDP_time;

byte Liczba_grzejacych;
float kondensacja;
word aktualne_pwm_odebrane_z_pompy;
word licz_sekundy_od_ostatniego_stanu_pompy;

/*
  This example requires Dallas Temperature Control library installed.
  https://github.com/milesburton/Arduino-Temperature-Control-Library
*/
// Add include to DS sensor
#include <supla/sensor/DS18B20.h>

#define CFG_BUTTON_GPIO 0
#define STATUS_LED_GPIO 2
//#define LED_RED_GPIO 13
//#define LED_BLUE_GPIO 12
#define OUTPUT_GPIO_1 5
#define OUTPUT_GPIO_2 13
#define OUTPUT_GPIO_3 14
#define OUTPUT_GPIO_4 27
#define OUTPUT_GPIO_5 25

#define wysylaj_przez_udp 1  //Zezwalaj na wysylanie danych przez UDP


String last_message[18];


Supla::ESPWifi wifi;
Supla::Eeprom eeprom;
Supla::LittleFsConfig configSupla;
Supla::Device::StatusLed statusLed(STATUS_LED_GPIO, true); // inverted state
Supla::EspWebServer suplaServer;


auto termometr_1 = new Supla::Sensor::VirtualThermometer;
auto termometr_2 = new Supla::Sensor::VirtualThermometer;
auto termometr_3 = new Supla::Sensor::VirtualThermometer;
auto termometr_4 = new Supla::Sensor::VirtualThermometer;
auto termometr_5 = new Supla::Sensor::VirtualThermometer;


Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_0 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_1 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_2 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_3 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_4 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_5 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_6 = nullptr;
Supla::Sensor::GeneralPurposeMeasurement *gpm_channel_7 = nullptr;


HTTPUpdateServer httpUpdater;

void setup() {
  Serial.begin(115200);


    gpm_channel_0 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_1 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_2 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_3 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_4 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_5 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_6 = new Supla::Sensor::GeneralPurposeMeasurement();
    gpm_channel_7 = new Supla::Sensor::GeneralPurposeMeasurement();


    gpm_channel_0->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_1->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_2->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_3->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_4->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_5->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_6->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);
    gpm_channel_7->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);


    gpm_channel_0->setDefaultUnitBeforeValue("");     gpm_channel_0->setDefaultUnitAfterValue("");    gpm_channel_0->setDefaultValuePrecision(0);      gpm_channel_0->setInitialCaption("Grzanie piec");
    gpm_channel_1->setDefaultUnitBeforeValue("");     gpm_channel_1->setDefaultUnitAfterValue("");    gpm_channel_1->setDefaultValuePrecision(0);      gpm_channel_1->setInitialCaption("PWM Pompa");
    gpm_channel_2->setDefaultUnitBeforeValue("");     gpm_channel_2->setDefaultUnitAfterValue("");    gpm_channel_2->setDefaultValuePrecision(0);      gpm_channel_2->setInitialCaption("Kondensacja");    
    gpm_channel_3->setDefaultUnitBeforeValue("");     gpm_channel_3->setDefaultUnitAfterValue("");    gpm_channel_3->setDefaultValuePrecision(0);      gpm_channel_3->setInitialCaption("Grzanie Salon");
    gpm_channel_4->setDefaultUnitBeforeValue("");     gpm_channel_4->setDefaultUnitAfterValue("");    gpm_channel_4->setDefaultValuePrecision(0);      gpm_channel_4->setInitialCaption("Grzanie Sypialnia");  
    gpm_channel_5->setDefaultUnitBeforeValue("");     gpm_channel_5->setDefaultUnitAfterValue("");    gpm_channel_5->setDefaultValuePrecision(0);      gpm_channel_5->setInitialCaption("Grzanie Pok. Zielony");
    gpm_channel_6->setDefaultUnitBeforeValue("");     gpm_channel_6->setDefaultUnitAfterValue("");    gpm_channel_6->setDefaultValuePrecision(0);      gpm_channel_6->setInitialCaption("Grzanie Pok. Niebieski");
    gpm_channel_7->setDefaultUnitBeforeValue("");     gpm_channel_7->setDefaultUnitAfterValue("");    gpm_channel_7->setDefaultValuePrecision(0);      gpm_channel_7->setInitialCaption("Grzanie Łazienka");



  

  // WARNING: using default Clock class. It works only when there is connection
  // with Supla server. In real thermostat application, use RTC HW clock,
  // which will keep time after ESP power reset
  new Supla::Clock;

  // HTML www component (they appear in sections according to creation
  // sequence)
  new Supla::Html::DeviceInfo(&SuplaDevice);
  new Supla::Html::WifiParameters;
  new Supla::Html::ProtocolParameters;
  new Supla::Html::StatusLedParameters;
  new Supla::Html::TimeParameters(&SuplaDevice);

  new Supla::Device::StatusLed(STATUS_LED_GPIO, true);
  eeprom.setStateSavePeriod(5000);

  auto output_1 = new Supla::Control::InternalPinOutput(OUTPUT_GPIO_1,false);
  auto output_2 = new Supla::Control::InternalPinOutput(OUTPUT_GPIO_2,false);
  auto output_3 = new Supla::Control::InternalPinOutput(OUTPUT_GPIO_3,false);
  auto output_4 = new Supla::Control::InternalPinOutput(OUTPUT_GPIO_4,false);
  auto output_5 = new Supla::Control::InternalPinOutput(OUTPUT_GPIO_5,false);



  auto hvac_1 = new Supla::Control::HvacBase(output_1);
  auto hvac_2 = new Supla::Control::HvacBase(output_2);
  auto hvac_3 = new Supla::Control::HvacBase(output_3);
  auto hvac_4 = new Supla::Control::HvacBase(output_4);
  auto hvac_5 = new Supla::Control::HvacBase(output_5);

  
  // Html page for HVAC
  new Supla::Html::HvacParameters(hvac_1);
  new Supla::Html::HvacParameters(hvac_2);
  new Supla::Html::HvacParameters(hvac_3);
  new Supla::Html::HvacParameters(hvac_4);
  new Supla::Html::HvacParameters(hvac_5);


  termometr_1->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC); 
  termometr_2->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC); 
  termometr_3->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC); 
  termometr_4->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC); 
  termometr_5->getChannel()->setValidityTimeSec(MAX_SLEEP_TIME_SEC);

  // Configure thermostat parameters
  hvac_1->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
  hvac_1->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2600);
  hvac_1->setTemperatureHisteresisMin(20);  // 0.2 degree
  hvac_1->setTemperatureHisteresisMax(1000);  // 10 degree
  hvac_1->setTemperatureHisteresis(20);

  hvac_2->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
  hvac_2->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2600);
  hvac_2->setTemperatureHisteresisMin(20);  // 0.2 degree
  hvac_2->setTemperatureHisteresisMax(1000);  // 10 degree
  hvac_2->setTemperatureHisteresis(20);

  hvac_3->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
  hvac_3->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2600);
  hvac_3->setTemperatureHisteresisMin(20);  // 0.2 degree
  hvac_3->setTemperatureHisteresisMax(1000);  // 10 degree
  hvac_3->setTemperatureHisteresis(20);

  hvac_4->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
  hvac_4->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2600);
  hvac_4->setTemperatureHisteresisMin(20);  // 0.2 degree
  hvac_4->setTemperatureHisteresisMax(1000);  // 10 degree
  hvac_4->setTemperatureHisteresis(20);

  hvac_5->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
  hvac_5->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2600);
  hvac_5->setTemperatureHisteresisMin(20);  // 0.2 degree
  hvac_5->setTemperatureHisteresisMax(1000);  // 10 degree
  hvac_5->setTemperatureHisteresis(20);

  auto cfgButton = new Supla::Control::Button(CFG_BUTTON_GPIO, true, true);
  cfgButton->configureAsConfigButton(&SuplaDevice);

  // configure defualt Supla CA certificate
  SuplaDevice.setSuplaCACert(suplaCACert);
  SuplaDevice.setSupla3rdPartyCACert(supla3rdCACert);

  SuplaDevice.setName("Termostat ESP32");
  
  httpUpdater.setup(suplaServer.getServerPtr(), "/update");
  SuplaDevice.begin(21); // Thermostat requires proto version >= 21
  

}

void loop() {

  
  
  if(timeout == 0){
    SuplaDevice.iterate();
    if(pierwsza_transmisja_UDP == 1){
      termometr_1->setValue(temp_aktualna[2]);    
      termometr_2->setValue(temp_aktualna[4]);
      termometr_3->setValue(temp_aktualna[5]);
      termometr_4->setValue(temp_aktualna[6]);
      termometr_5->setValue(temp_aktualna[15]);
    }
    gpm_channel_0->setValue(Liczba_grzejacych);
    if(licz_sekundy_od_ostatniego_stanu_pompy < 120){    
      gpm_channel_1->setValue(aktualne_pwm_odebrane_z_pompy);
    }
    if(licz_sekundy_od_ostatniego_stanu_pompy >= 120){     
      gpm_channel_1->setValue(-1);
    }    
    gpm_channel_2->setValue(kondensacja);    
    gpm_channel_3->setValue(grzanie[2]);    
    gpm_channel_4->setValue(grzanie[4]);    
    gpm_channel_5->setValue(grzanie[5]);    
    gpm_channel_6->setValue(grzanie[6]);    
    gpm_channel_7->setValue(grzanie[15]);    
  }

  if (SuplaDevice.getDeviceMode() == Supla::DEVICE_MODE_NORMAL) {
    if (WiFi.status() == WL_CONNECTED) { 
      if(wykonaj_raz < 10000){
        ++wykonaj_raz;
      }
      if(wykonaj_raz == 10000){
        wykonaj_raz = 10001;
          Serial.println("UDP begin");
          delay(1000); 
          udp.begin(udpPort);  
      }
    }
    Odczytaj_UDP();
    Wyslij_UDP();
  }

  if (Supla::Network::IsReady()) {
    SuplaDevice.handleAction(0, Supla::START_LOCAL_WEB_SERVER);
  }

  /*
  if (SuplaDevice.getDeviceMode() == Supla::DEVICE_MODE_CONFIG) {
    // CONFIG MODE
  }


  if(wykonaj_raz == 10001){
    if (SuplaDevice.getDeviceMode() == Supla::DEVICE_MODE_NORMAL) {

    }
  }
  */  

  

  if(timeout > 0){
    if(timeout == 1){
      Serial.println("timeout");
    }
    --timeout;
  }
  
  Odczytaj_stan_wyjsc_hvac();
}


void Odczytaj_stan_wyjsc_hvac(){

  int state_pomocniczy;
  int state_pomocniczy_2;

  state_pomocniczy = digitalRead(OUTPUT_GPIO_1); if(state_pomocniczy == 0){state_pomocniczy_2 = 1;} if(state_pomocniczy == 1){state_pomocniczy_2 = 0;} state_output_[2] = state_pomocniczy_2; 
  state_pomocniczy = digitalRead(OUTPUT_GPIO_2); if(state_pomocniczy == 0){state_pomocniczy_2 = 1;} if(state_pomocniczy == 1){state_pomocniczy_2 = 0;} state_output_[4] = state_pomocniczy_2;
  state_pomocniczy = digitalRead(OUTPUT_GPIO_3); if(state_pomocniczy == 0){state_pomocniczy_2 = 1;} if(state_pomocniczy == 1){state_pomocniczy_2 = 0;} state_output_[5] = state_pomocniczy_2;
  state_pomocniczy = digitalRead(OUTPUT_GPIO_4); if(state_pomocniczy == 0){state_pomocniczy_2 = 1;} if(state_pomocniczy == 1){state_pomocniczy_2 = 0;} state_output_[6] = state_pomocniczy_2;
  state_pomocniczy = digitalRead(OUTPUT_GPIO_5); if(state_pomocniczy == 0){state_pomocniczy_2 = 1;} if(state_pomocniczy == 1){state_pomocniczy_2 = 0;} state_output_[15] = state_pomocniczy_2;




  //Serial.println(hvac_1->isOn());


  
  
  for (byte licz = 1; licz <= 16; licz++) {
    if(state_output_old_[licz] != state_output_[licz]){ 
      state_output_old_[licz] = state_output_[licz];
      nowe_dane_udp_do_wyslania = 1;
      if(state_output_[licz] == 1){grzanie[licz] = 1;}else{grzanie[licz] = 0;}
      if(licz == 2) {Serial.println("Status hvac 1 = " + channel_name[licz] + " " + String(grzanie[licz]));}
      if(licz == 4) {Serial.println("Status hvac 2 = " + channel_name[licz] + " " + String(grzanie[licz]));}
      if(licz == 5) {Serial.println("Status hvac 3 = " + channel_name[licz] + " " + String(grzanie[licz]));}
      if(licz == 6) {Serial.println("Status hvac 4 = " + channel_name[licz] + " " + String(grzanie[licz]));}
      if(licz == 15){Serial.println("Status hvac 5 = " + channel_name[licz] + " " + String(grzanie[licz]));}  
    }
  }

  Liczba_grzejacych = 0;
  for (byte licz = 1; licz <= 16; licz++) {
    if(grzanie[licz] == 1){
      ++Liczba_grzejacych;
    }  
  }
  kondensacja = temp_aktualna[9] - temp_aktualna[10];
  
  
  
}



void Wyslij_UDP(){

    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis_UDP_time >= 1000UL){
      previousMillis_UDP_time = currentMillis;
      ++sekundy_od_ostatniej_transmisji_UDP_TX;
      ++licz_sekundy_od_ostatniego_stanu_pompy;
      if(licz_sekundy_od_ostatniego_stanu_pompy >= 120){     
        licz_sekundy_od_ostatniego_stanu_pompy = 120;  
      }
    }

    if(sekundy_od_ostatniej_transmisji_UDP_TX > 10){
      sekundy_od_ostatniej_transmisji_UDP_TX = 0;
      nowe_dane_udp_do_wyslania = 1;
    }

  
    if(nowe_dane_udp_do_wyslania > 0){
      String text_UDP;
      if(nowe_dane_udp_do_wyslania >= 1){
        sekundy_od_ostatniej_transmisji_UDP_TX = 0;
        nowe_dane_udp_do_wyslania = 1;  //ograniczam żeby wysyłanie nie trwało w nieskończonośc
      }
  
      
      if(currentMillis - previousMillis_UDP >= 60UL){
        previousMillis_UDP = currentMillis;
        ++numer_kanalu_do_wyslania_przez_UDP;

        String text_UDP;
        
        if(numer_kanalu_do_wyslania_przez_UDP < 17){
          
          text_UDP = "{";
          text_UDP += "\"ID\":\"" + String(numer_kanalu_do_wyslania_przez_UDP)               + "\", "; 
          text_UDP += "\"Name\":\"" + channel_name[numer_kanalu_do_wyslania_przez_UDP]       + "\", ";  // <---Dodatkowe znaki cudzyslowia, przesylamy wartosc jako tekst, nie jako liczbę
          text_UDP += "\"Temp\":\"" + String(temp_aktualna[numer_kanalu_do_wyslania_przez_UDP])     + "\", ";    
          text_UDP += "\"Heat\":\"" + String(grzanie[numer_kanalu_do_wyslania_przez_UDP]) + "\"} ";
          
          if(wysylaj_przez_udp == 1){
            udp.beginPacket("192.168.2.255", udpPort); udp.print(text_UDP); udp.endPacket();yield();
          }else{
            
            Serial.print("UDP TX: ");
            Serial.println(text_UDP);
            
          }
        }

        if(numer_kanalu_do_wyslania_przez_UDP == 17){
          word PWM_dla_pompy = 0;
          for (byte licz = 1; licz <= 16; licz++) {
            if(grzanie[licz] == 1){
              if(licz == 2){
                PWM_dla_pompy = PWM_dla_pompy + 1000;  //Dla salonu daj 1000
              }else{
                PWM_dla_pompy = PWM_dla_pompy + 250;   //Dla pozostałych pomieszczen daj 250
              }
            }
          }
          if(PWM_dla_pompy > 1000){
            PWM_dla_pompy = 1000;
          }
          
          word randNumber1  = random(1024);
          word randNumber2  = random(1024);
          word randNumber3  = random(1024);
          word randNumber4  = random(1024);
          word PUMP_CRC = 0;
          PUMP_CRC = PUMP_CRC + randNumber1;
          PUMP_CRC = PUMP_CRC + randNumber2;
          PUMP_CRC = PUMP_CRC + randNumber3;
          PUMP_CRC = PUMP_CRC + randNumber4;
          PUMP_CRC = PUMP_CRC + PWM_dla_pompy;

          text_UDP = "{";
          text_UDP += "\"ID\":\"Pompa_1\", "; 
          text_UDP += "\"Name\":\"Pompa_PWM\", ";  // <---Dodatkowe znaki cudzyslowia, przesylamy wartosc jako tekst, nie jako liczbę 
          text_UDP += "\"PWM_1\":\"" + String(randNumber1)     + "\", ";       //Wysylamy dowolna wartosc
          text_UDP += "\"PWM_2\":\"" + String(randNumber2)     + "\", ";       //Wysylamy dowolna wartosc
          text_UDP += "\"PWM_3\":\"" + String(randNumber3)     + "\", ";       //Wysylamy dowolna wartosc
          text_UDP += "\"PWM_4\":\"" + String(randNumber4)     + "\", ";       //Wysylamy dowolna wartosc
          text_UDP += "\"PWM_5\":\"" + String(PWM_dla_pompy)   + "\", ";       //Wysylamy dowolna wartosc
          text_UDP += "\"Pompa_CRC\":\"" + String(PUMP_CRC) + "\"} ";
          if(wysylaj_przez_udp == 1){
            udp.beginPacket("192.168.2.255", udpPort); udp.print(text_UDP); udp.endPacket();yield();
          }else{
            Serial.print("UDP TX: ");
            Serial.println(text_UDP);
          }
        }
      }
  
      if(numer_kanalu_do_wyslania_przez_UDP >= 17){
        numer_kanalu_do_wyslania_przez_UDP = 0;
        nowe_dane_udp_do_wyslania = 0;
        sekundy_od_ostatniej_transmisji_UDP_TX = 0;
      }
    }
}  





void Odczytaj_UDP(){
  int packetSize = udp.parsePacket();
    
  if (packetSize)
  {
    digitalWrite(STATUS_LED_GPIO,HIGH);
    delay(30);
    // receive incoming UDP packets
    //Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
    int len = udp.read(incomingPacket, 255);
    if (len > 0)
    {
      incomingPacket[len] = 0;
    }
    udp_msg = String(incomingPacket);
    if (udp_msg.substring(2,9) == "CzID255") {
      Dekoduj_json_udp();
    }
    if (udp_msg.substring(7,14) == "Pompa_1") {
      Dekoduj_json_udp();
    }
    udp_msg = "";
    digitalWrite(STATUS_LED_GPIO,LOW);
  }
}

void Dekoduj_json_udp(){

  byte ID_val = 0;


  //Serial.println(msg);
      

  //Kod wygenerowany przy pomocy strony https://arduinojson.org/v6/assistant/
     
  DynamicJsonDocument doc(1024);

  DeserializationError err = deserializeJson(doc, udp_msg);
  if (err) {
    
    Serial.println(F("Blad dokodowania JSON"));
    return;
  }
      
  deserializeJson(doc, udp_msg);
  String    ID_string = doc["CzID255"];
  String  Name_string = doc["CzN255"];     
  String  Temp_string = doc["CzT255"];         

  String    Pompa_string = doc["ID"];
  String    Pompa_status_string = doc["STATUS"];
  String    Pompa_DATA_1 = doc["DATA_1"];
  String    Pompa_DATA_2 = doc["DATA_2"];
  String    Pompa_DATA_3 = doc["DATA_3"];
  String    Pompa_DATA_4 = doc["DATA_4"];
  String    Pompa_DATA_5 = doc["DATA_5"];
  String    Pompa_DATA_CRC = doc["DATA_CRC"];

  String    Start_string = doc["255_START"];
  String    End_string = doc["255_END"];

  //Serial.println(msg.substring(2,9));
  //Serial.println(udp_msg);




  if (udp_msg.substring(7,14) == "Pompa_1") {
    if(Pompa_string == "Pompa_1" && Pompa_status_string == "OK"){
  
      int Pompa_DATA_1_int = Pompa_DATA_1.toInt();
      int Pompa_DATA_2_int = Pompa_DATA_2.toInt();
      int Pompa_DATA_3_int = Pompa_DATA_3.toInt();
      int Pompa_DATA_4_int = Pompa_DATA_4.toInt();
      int Pompa_DATA_5_int = Pompa_DATA_5.toInt();
      int Pompa_DATA_CRC_int = Pompa_DATA_CRC.toInt();
  
      word licz_crc = 0;
      licz_crc = licz_crc + Pompa_DATA_1_int;
      licz_crc = licz_crc + Pompa_DATA_2_int;
      licz_crc = licz_crc + Pompa_DATA_3_int;
      licz_crc = licz_crc + Pompa_DATA_4_int;
      licz_crc = licz_crc + Pompa_DATA_5_int;
  
      if(licz_crc == Pompa_DATA_CRC_int){
        aktualne_pwm_odebrane_z_pompy = Pompa_DATA_5_int;
        licz_sekundy_od_ostatniego_stanu_pompy = 0;
      }
    }
  }


  



  
  if (udp_msg.substring(2,9) == "CzID255") {
    //Serial.println(udp_msg);

    ID_val = ID_string.toInt();

    last_message[ID_val] = udp_msg;
    channel_name[ID_val] = Name_string;
    if(ID_val == 0){
      temp_aktualna_unsigned_long = Temp_string.toInt();
      timeout = 50000; 
      
    }else{
      temp_aktualna_word[ID_val] = Temp_string.toInt();
      timeout = 50000;
    }

    if(ID_val == 16){
      timeout = 0;
      //Kalkulacja CRC
  
      unsigned long CRC = 0;
      for (byte licz = 1; licz <= 16; licz++) {
        CRC = CRC + temp_aktualna_word[licz];   
      }
   
      if(CRC == temp_aktualna_unsigned_long){ //Jesli otrzymalismy prawidlowe CRC;
        
        float temp_aktualna_float = 0;
        for (byte licz = 1; licz <= 16; licz++) {
          
          temp_aktualna_float = temp_aktualna_word[licz] - 12721;   //Deszyfrujemy dane
          temp_aktualna[licz] = temp_aktualna_float;
          temp_aktualna[licz] = temp_aktualna[licz] / 100;
        }
        pierwsza_transmisja_UDP = 1;
        kasuj_wszystkie_msg();
        
      }else{
        if(temp_aktualna_unsigned_long == 0){          
            Serial.println(F("CRC blędne, nieodebrano calej ramki danych"));
            
            korekcja_bledow();
            kasuj_wszystkie_msg();
        }else{        
            Serial.print(F("CRC blędne, oczekiwano: "));
            Serial.print(String(temp_aktualna_unsigned_long));
            Serial.print(F(" jest: "));
            Serial.println(String(CRC));
            
            korekcja_bledow();
            kasuj_wszystkie_msg();
        }
      }
      temp_aktualna_unsigned_long = random(30000);  //Usuwamy dane zapisujac ja dowolnymi danymi
      for (byte licz = 1; licz <= 16; licz++) {
        
        temp_aktualna_word[licz] = random(30000);  //Usuwamy dane zapisujac ja dowolnymi danymi
      }
    }
      
  }
  
}

void korekcja_bledow(){
  byte liczba_brakujacych_transmisji;
  byte zapamietaj_numer_brakujacej_transmisji;
  unsigned long suma;
  unsigned long roznica;
  for (byte licz = 0; licz <= 16; licz++) {
    if(last_message[licz] == ""){
      ++liczba_brakujacych_transmisji;
      zapamietaj_numer_brakujacej_transmisji = licz;  
    }
  } 

  if(liczba_brakujacych_transmisji > 0){
    Serial.print("Liczba brakujacych transmisji: ");
    Serial.println(liczba_brakujacych_transmisji);
    if(liczba_brakujacych_transmisji == 1){
      //Serial.print("Numer brakujacej transmisji:   ");
      //Serial.println(zapamietaj_numer_brakujacej_transmisji);

      if(zapamietaj_numer_brakujacej_transmisji != 0){
        suma = 0;
        for (byte licz = 1; licz <= 16; licz++) {
          if(licz != zapamietaj_numer_brakujacej_transmisji){
            suma = suma + temp_aktualna_word[licz];    
          }
        }
        //Serial.print("Suma:    ");
        //Serial.println(suma);
        roznica = temp_aktualna_unsigned_long - suma;
        //Serial.print("Różnica: ");
        //Serial.println(roznica);

        if(roznica < 100000){
          temp_aktualna_word[zapamietaj_numer_brakujacej_transmisji] = roznica;  
          float temp_aktualna_float = 0;
          for (byte licz = 1; licz <= 16; licz++) {
            temp_aktualna_float = temp_aktualna_word[licz] - 12721;   //Deszyfrujemy dane
            temp_aktualna[licz] = temp_aktualna_float;
            temp_aktualna[licz] = temp_aktualna[licz] / 100;
          }
          Serial.print("Naprawiono blad transmisji nr: ");
          Serial.print(zapamietaj_numer_brakujacej_transmisji);
          Serial.print(" Wartosc: ");
          Serial.print(roznica);
          Serial.print(" --> ");
          Serial.print(String(temp_aktualna[zapamietaj_numer_brakujacej_transmisji],1));
          Serial.println("*C");
        }else{
          Serial.println("Nienaprawialne, roznica wieksza / rowna 100000");  
        }
        
      }else{
        Serial.println("Nienaprawialne, brakuje transmisji 0");  
      }




      
    }else{
      Serial.println("Nienaprawialne, za duzo brakuje");
    }
  }
   
}




void kasuj_wszystkie_msg(){
  for (byte licz = 0; licz <= 16; licz++) {
    last_message[licz] = "";  
  }
}
radzik_r
Posts: 468
Joined: Sun Aug 11, 2019 5:32 pm
Has thanked: 1 time
Been thanked: 2 times

Post

potwierdzam,
nie jednokrotnie tez tak miałem,
przeważnie podczas eksperymentów/testów zabawy z podłączaniem/odłączaniem szybkim itp.

ale jak już uruchomiony skonfigurowany i działa przez jakiś czas godziny/dni tygodnie to jest ok

być może podczas takich eksperymentów z pamięcią się coś dzieje, może nie nadąża zapisać/odczytać itp. tak tylko podejrzewam
User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Nie jest to bezpieczne. Można sobie zdalnie rozsypać configa będąc daleko poza domem. Powinna być jakaś programowa alternatywa że skoro nie umie się podłączyć przez konfiga to jakoś zapasowym łączem / ustawieniami.

Nie rozumiem też czemu przy każdym czyszczeniu procesora generuje nowy guid
User avatar
lukfud
Posts: 2480
Joined: Thu Nov 23, 2017 11:33 pm
Location: Warszawa
Has thanked: 13 times
Been thanked: 11 times

Post

"czyszczeniu procesora"? masz na myśli kasowaniu flash'a?
https://www.facebook.com/groups/supladiy
https://www.facebook.com/groups/suplazamel
https://www.facebook.com/groups/suplaauraton
https://smartnerzeczy.pl
User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Jest w Arduino opcja erase flash. Domyślnie mam ją jako disable. Ale jak załącze to wiadomo kasuje wszystko. Na podstawie czego guid jest generowany? MAC adres + ilość funkcji + data kompilacji + nazwa pliku ino?

Najchętniej to to na sztywno ustawie. Wolę mieć channel conflikt niż ciągle wszystko ustawiać od zera przy modyfikacjach softu. Jest to męczące. Z ustawieniami od zera najbardziej męczyłem się przy esp32 który ma 80 kanałów. To była masakra. Ustawiłem guidy, email i wifi na sztywno i jakoś to pracuje.
zzrr
Posts: 1864
Joined: Wed Oct 26, 2022 7:35 pm
Has thanked: 76 times
Been thanked: 119 times

Post

Duch__ wrote: Wed Nov 13, 2024 11:56 am Jest w Arduino opcja erase flash. Domyślnie mam ją jako disable. Ale jak załącze to wiadomo kasuje wszystko. Na podstawie czego guid jest generowany? MAC adres + ilość funkcji + data kompilacji + nazwa pliku ino?
Dołączam się do pytania. A co do niespodziewanego skasowanie flash to faktycznie jest problemowe. Też z tym walczyłem nie dawno, wyszło przy eksperymentowaniu jak to ujął @radzik_r. Dodałem argument dla klasy Supla::LittleFsConfig configSupla(3000); i zrobiłem offset dla eeprom. Wydawało się że pomogło. Układ w normalnych warunkach działał bez jakichkolwiek problemów ok. 3 miesiące. Tydzień temu, przy wyłączeniu i włączeniu zasilania trach i flash czysty. To się dzieje w trakcie startowania modułu. Część mojego kodu wtedy @klew widział i "rzucił" wzmiankę że nie widzi żadnych zabezpieczeń w kodzie. Zdaje się że chodziło o jakieś zabezpieczenie właśnie flash przed skasowaniem. Nie wnikałem bo myślałem że problem się rozwiązał. Osobiście nie wiem jak takie zabezpieczenie zrobić i gdyby @klew czy ktokolwiek kto wie napisał jak to zrobić, osobiście byłbym wdzięczny.
User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Pół biedy jak wyleci ssid czy dane do konta. Jak szlak trafi temp setpoint i wkradnie się tam wartość np 0 stopni albo 28 to będąc na urlopie albo zastaniemy potrzaskane od zimna instalacje albo tropiki. W obu przypadkach zbędne koszty.

Możliwość zmiany wszystkich strategicznych parametrów powinna być potwierdzona chociażby nawet głupim kodem typu 1234 czy flagą zezwalającą, tak że procesor nie otrzymując tego kodu / flagi nie ma prawa dokonać żadnych zmian we flashu. Coś na wzór wpisania komendy potwierdzającej reset licznika energii. Sam przycisk "zapisz" to za mało
User avatar
Duch__
Posts: 2199
Joined: Wed Aug 24, 2016 7:26 pm
Location: Opole
Been thanked: 6 times

Post

Czemu te procedury:

Code: Select all

  hvac_1->setUsedAlgorithm(SUPLA_HVAC_ALGORITHM_ON_OFF_SETPOINT_AT_MOST);  
  hvac_1->setMinOnTimeS(120);       
  hvac_1->setMinOffTimeS(180);      
  hvac_1->setTemperatureFreezeProtection(1100);
  hvac_1->setTemperatureHeatProtection(2700);
  hvac_1->setTemperatureEco(2200);
  hvac_1->setTemperatureComfort(2300);
  hvac_1->setTemperatureAboveAlarm(2750);
  hvac_1->setTemperatureBelowAlarm(1050);
ustawione w

Code: Select all

void setup() {}
nie działają?

Chciałbym żeby na dzień dobry ustawiło mi te wartości bym nie musiał ich na nowo ustawiać przy każdej nowej, testowej rejestracji termostatu.

Return to “Ogólna dyskusja”