Sterowanie klimatyzacją

Masz pomysł na funkcjonalność lub koncepcję na rozwój projektu. Opisz wszystko tutaj.
User avatar
bMind
Posts: 35
Joined: Fri Apr 01, 2016 11:33 am

Post

Witam,

Chętnie zobaczył bym w Supli możliwość sterowania klimatyzacją. Wiem, że są apki na Androida, można też coś poskładać samemu na bazie Arduino czy ESP, ale myślę że jednak możliwość kontroli tego z Supli była by naprawdę fajną opcją. Dodatkowo daje to jakieś możliwości rozwoju na przyszłość. Można zacząć od podstawowych funkcji jak włącz/wyłącz, ustaw temperaturę a potem iść w kierunku harmonogramów i trochę większej automatyzacji pracy klimatyzatora. Inteligentny dom jak się patrzy ;)

Pozdrawiam :)
User avatar
slawek
Posts: 2685
Joined: Mon Mar 14, 2016 11:48 pm
Location: Biała Podlaska

Post

Podpisuję się pod pomysłem...ale to nie będzie chyba proste, bo większość małych klimatyzatorów jest sterowana pilotem IR i pewnie trzeba niemałej ingerencji w elektronikę... chyba że podpiąć np. ESP do pilota...
TEORIA jest wtedy gdy wszystko wiemy i nic nie działa
PRAKTYKA jest wtedy gdy wszystko działa a my nie wiemy dlaczego
My łączymy teorię z praktyką czyli nic nie działa i nikt nie wie dlaczego
User avatar
bMind
Posts: 35
Joined: Fri Apr 01, 2016 11:33 am

Post

Ingerencję? Nie sądzę. Z tego co patrzyłem na projekty w oparciu na Arduino to była raczej kwestia nadajnika IR do wysyłania i odbiornika żeby zakodować sygnały - http://www.instructables.com/id/How-to- ... home-with/. Ale znów apki na Androida działają inaczej, bo odpada etap kodowania - wybiera się producenta i w sumie już. Kody sterowania są raczej stałe i przypisane do producenta więc to raczej kwestia, że je po prostu hardkodują w programie. Ale będę kontynuował drążenie tematu jakoś równolegle do mojego pytania tutaj.
Enc
Posts: 41
Joined: Wed Apr 27, 2016 3:02 pm

Post

Ja zrobiłem na ESP transceiver który działa dwukierunkowo w relacji IR <-> MQTT. Steruję z niego sprzętem audio i wysyłam komendy do urządzeń, których nie mogę obsłużyć po IP - np. mam TV który obsługuję po IP ale jest jedna komenda której nie da się zrobić po IP - Power ON :) . Można do takiego tranceivera dodać np. własne RAW kody - AC zazwyczaj nie działa na typowych kodach, a do tego jeszcze wciśnięcie klawisza wysyła komplet ustawień. Poniżej kod dla ESP (w wersji Arduino/Platformio)
Zrobiłem to na ESP01 - Odbiornik IR podłączony jest do GPIO2 a dioda nadawcza przez tranzystor wzmacniający do GPIO3 (RX portu szeregowego) + standardowe podciągi do +3,3v

Code: Select all

/*
 * MQTT IR server
 * An IR LED must be connected to ESP8266 pin GPIO-3
 * An IR receiver to pin GPIO-2
 * used library:
 * https://github.com/markszabo/IRremoteESP8266
 * Version 0.1 January, 2016
 */

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <IRremoteESP8266.h>
#include <PubSubClient.h>

// PIN definition

#define RECV_PIN 2
#define SEND_PIN 3

const char* ssid = "....";
const char* password = "....";

const char* topicRaport = "esp8266/02/info";
const char* topicSubscribe = "esp8266/02/sender/#";
const char* topicPrefix = "esp8266/02/receiver";

const char* mqtt_server = "....";
const char* mqtt_user = "...";
const char* mqtt_pass = "...";

String clientName; // MQTT client name
char message_buff[100];

IRrecv irrecv(RECV_PIN);

IRsend irsend(SEND_PIN);

WiFiClient wifiClient;


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

PubSubClient client(mqtt_server, 1883, callback, wifiClient);

// -----------------------------------------------------------------
// MQTT receiver
void callback(char* topic, byte* payload, unsigned int length) {
  int i = 0;

  Serial.println("Message arrived:  topic: " + String(topic));
  Serial.println("Length: " + String(length,DEC));

  // create character buffer with ending null terminator (string)
  for(i=0; i<length; i++) {
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';
  
  unsigned int freq=38;
  String msgString = String(message_buff);
  String msgTopic = String(topic);
  unsigned long msgInt = msgString.toInt();
  
  unsigned int  rawData_s1[35] = {250,950, 200,2000, 200,1200, 200,2850, 200,1350, 200,1350, 200,1050, 200,2150, 200,12950, 200,950, 200,1200, 200,800, 200,1200, 200,1600, 200,1200, 200,800, 200,800, 200};  // UNKNOWN C0092718
  unsigned int  rawData_s2[37] = {100,5850, 200,950, 200,2000, 200,1200, 200,2850, 200,1350, 200,1350, 200,1050, 200,2150, 200,12950, 200,950, 200,2300, 200,1900, 200,1200, 200,1650, 200,1200, 200,800, 200,800, 200};  // UNKNOWN 4AE2F613
  unsigned int  rawData_11[35] = {250,950, 200,2000, 200,1250, 200,2850, 200,1350, 200,1350, 200,1050, 200,2150, 200,12950, 200,950, 200,800, 200,800, 200,1200, 200,800, 200,2450, 200,800, 200,800, 200};  // UNKNOWN 290BC97A
  unsigned int  rawData_12[35] = {250,950, 200,2000, 200,1200, 200,2850, 200,1350, 200,1350, 200,1050, 200,2150, 200,12950, 200,950, 200,1900, 200,1900, 200,1200, 200,800, 200,2450, 200,800, 200,800, 200};  // UNKNOWN 8FEB0411
  unsigned int  rawData_91[35] = {250,950, 200,2000, 200,1200, 200,2850, 200,1350, 200,1350, 200,1100, 200,2150, 200,12950, 200,950, 200,1750, 200,800, 200,1200, 200,1200, 200,1100, 200,800, 200,800, 200};  // UNKNOWN 19B50A9
  unsigned int  rawData_92[35] = {250,950, 200,2000, 200,1250, 200,2850, 200,1350, 200,1350, 200,1100, 200,2150, 200,12950, 200,950, 200,2850, 200,1900, 200,1200, 200,1200, 200,1100, 200,800, 200,800, 200};  // UNKNOWN 442CD28F


  Serial.println("Payload String: " + msgString);
  if (msgTopic=="esp8266/02/sender/NC/HDMI") // *9
  {
    irsend.sendRaw(rawData_s1, 35, freq);
    irsend.sendRaw(rawData_s2, 37, freq);
    irsend.sendRaw(rawData_91, 35, freq);
    irsend.sendRaw(rawData_92, 35, freq);
    Serial.println("Send NC+ HDMI: *9");
  } 
  else if (msgTopic=="esp8266/02/sender/NC/EURO") // *1
  {
    irsend.sendRaw(rawData_s1, 35, freq);
    irsend.sendRaw(rawData_s2, 37, freq);
    irsend.sendRaw(rawData_11, 35, freq);
    irsend.sendRaw(rawData_12, 35, freq);
    Serial.println("Send NC+ EURO: *1");
  } else {
    // struktura "esp8266/02/sender/typ[/bits[/panasonic_address]]"
    int endOfBits;
    String irTypStr = "";
    String irBitsStr = "";
    int irBitsInt=-1;
    String irPanasAddrStr = "";
    
    int endOfTyp = msgTopic.indexOf("/",20);
    if (endOfTyp == -1)
    {
      // One element - only irTyp
      irTypStr  = msgTopic.substring(18);
    } else {
      // irTyp exists i cos dalej
      irTypStr  = msgTopic.substring(18, endOfTyp);
      endOfBits = msgTopic.indexOf("/",endOfTyp+1);
      if (endOfBits== -1)
      {
        // irBits jest na koncy
        irBitsStr = msgTopic.substring(endOfTyp+1);
      } else {
        // irBits i cos dalej
        irBitsStr = msgTopic.substring(endOfTyp+1, endOfBits);
        irPanasAddrStr = msgTopic.substring(endOfBits+1);
      }
      irBitsInt = irBitsStr.toInt();
    }
    
    
    Serial.println(irTypStr);
    Serial.println(irBitsStr);
    Serial.println(irPanasAddrStr);
    if (irTypStr=="NEC") {
      Serial.print("Send NEC:");
      Serial.println(msgInt);
      irsend.sendNEC(msgInt, 36);
    } else if (irTypStr=="RC5") {
      Serial.print("Send RC5:");
      Serial.print(msgInt);
      Serial.print(" (");
      Serial.print(irBitsInt);
      Serial.println("-bits)");
      irsend.sendRC5(msgInt, irBitsInt);
    }
/*
 TODO:
      case "UNKNOWN":      
      case "SONY":
      case "RC6":
      case "DISH":
      case "SHARP":
      case "JVC":
      case "SANYO":
      case "MITSUBISHI":
      case "SAMSUNG":
      case "LG":
      case "WHYNTER":
      case "AIWA_RC_T501":
      case "PANASONIC":
  */  
  }  
}


// -----------------------------------------------------------------
String macToStr(const uint8_t* mac)
{
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);
    if (i < 5)
      result += ':';
  }
  return result;
}

// -----------------------------------------------------------------
void setup(void){
  irsend.begin();		// Start IR sender
  irrecv.enableIRIn();  // Start the receiver

  Serial.begin(115200,SERIAL_8N1,SERIAL_TX_ONLY);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  

  clientName += "esp8266-";
  uint8_t mac[6];
  WiFi.macAddress(mac);
  clientName += macToStr(mac);
  clientName += "-";
  clientName += String(micros() & 0xff, 16);

  connect_to_MQTT();
}

// -----------------------------------------------------------------
void connect_to_MQTT() {
  Serial.print("Connecting to ");
  Serial.print(mqtt_server);
  Serial.print(" as ");
  Serial.println(clientName);

  int is_conn = 0;
  while (is_conn == 0) {
    if (client.connect((char*) clientName.c_str(), mqtt_user, mqtt_pass)) {
      Serial.println("Connected to MQTT broker");
      client.publish(topicRaport, (char*) clientName.c_str());
      IPAddress myIp = WiFi.localIP();
      char myIpString[24];
      sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]);
      client.publish(topicRaport, (char*) myIpString);

      Serial.print("Topic is: ");
      Serial.println(topicSubscribe);
      if (client.subscribe(topicSubscribe)){
        Serial.println("Successfully subscribed");
      }

      is_conn = 1;
    }
    else {
      Serial.print("MQTT connect failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// -----------------------------------------------------------------
// Encodig of data
void  encoding (decode_results *results, char * result_encoding)
{
  switch (results->decode_type) {
    default:
    case UNKNOWN:      strncpy(result_encoding,"UNKNOWN\0",8);       break ;
    case NEC:          strncpy(result_encoding,"NEC\0",4);           break ;
    case SONY:         strncpy(result_encoding,"SONY\0",5);          break ;
    case RC5:          strncpy(result_encoding,"RC5\0",4);           break ;
    case RC6:          strncpy(result_encoding,"RC6\0",4);           break ;
    case DISH:         strncpy(result_encoding,"DISH\0",5);          break ;
    case SHARP:        strncpy(result_encoding,"SHARP\0",6);         break ;
    case JVC:          strncpy(result_encoding,"JVC\0",4);           break ;
    case SANYO:        strncpy(result_encoding,"SANYO\0",6);         break ;
    case MITSUBISHI:   strncpy(result_encoding,"MITSUBISHI\0",11);   break ;
    case SAMSUNG:      strncpy(result_encoding,"SAMSUNG\0",8);       break ;
    case LG:           strncpy(result_encoding,"LG\0",3);            break ;
    case WHYNTER:      strncpy(result_encoding,"WHYNTER\0",8);       break ;
    case AIWA_RC_T501: strncpy(result_encoding,"AIWA_RC_T501\0",13); break ;
    case PANASONIC:    strncpy(result_encoding,"PANASONIC\0",11);    break ;
  }
}

// -----------------------------------------------------------------
void loop(void){
  client.loop();

  if (! client.connected()) {
    Serial.println("Not connected to MQTT....");
    connect_to_MQTT();
  }
  decode_results  results;        // Somewhere to store the results
  if (irrecv.decode(&results)) {  // Grab an IR code
    char myTopic[100];
    char myTmp[50];
    char myValue[500];
    encoding (&results, myTmp);
    if (results.decode_type == PANASONIC) { //Panasonic has address
      // struktura "prefix/typ/bits[/panasonic_address]"
      sprintf(myTopic, "%s/%s/%d/%d", topicPrefix, myTmp, results.bits, results.panasonicAddress );
    } else {
      sprintf(myTopic, "%s/%s/%d", topicPrefix, myTmp, results.bits );
    }
    if (results.decode_type != UNKNOWN) {
      sprintf(myValue, "%d", results.value);
      client.publish((char*) myTopic, (char*) myValue );
    }
    irrecv.resume();              // Prepare for the next value
  }
} 
Nowa wersja będzie operata o bibliotekę homie i miała tryb konfiguracji WIFI+MQTT. Mam plan na tryb uczenia się i zapamiętywania sekwencji RAW kodów IR na flashu. Tylko czasu brak, a to co zrobiłem robi to co potrzebuję więc nie ma motywacji :)
User avatar
bMind
Posts: 35
Joined: Fri Apr 01, 2016 11:33 am

Post

Ooo..to już jakiś początek :) Dzięki!
Enc
Posts: 41
Joined: Wed Apr 27, 2016 3:02 pm

Post

Aktualna wersja dostępna jest na Github-ie: https://github.com/enc-X/mqtt-ir-transceiver
percy
Posts: 31
Joined: Thu Feb 02, 2017 8:11 pm

Post

Podobno niedawno pojawił się interfejs IR Controller Shield do Wemos D1 mini. Może komuś uda się przystosować to do Supli.

Return to “Pomysły i koncepcje”