Objective

The AEG induction hob has an interesting “Hob2Hood” functionality that allows you to send commands to the hood - switching on the lights and adjusting the suction power according to what’s happening on the hob. Unfortunately, this is only useful if the hood also supports the same functionality. Our hood is from a different manufacturer, which makes it useless. Or does it?

Hob2Hood uses an IR signal to communicate with the hood. An IR diode is integrated in the hob, similar to the one in a classic TV remote control. On the other side, the cooker hood, which also supports Hob2Hood, receives the IR signal and adjusts its operation. The cooker hood we have has an IR receiver (and a remote control), but it does not understand the commands sent by the hob.

The solution is a device that plays the role of interpreting the hobs’s commands and translating them into commands that the hood understands. All we need is an IR receiver, an IR transmitter and a microcontroller to interpret and translate the signals.

Hardware

The construction of the device is described on my Github, together with the code that translates the IR signals. I have made some programming changes since the original project, namely the NodeMCU microcontroller no longer uses the code from the above Github project, but the OpenMQTTGateway firmware, which in my case allows remote control of the IR modules via the MQTT protocol. This moved the logic from the microcontroller to Home Assistant, but left it mostly unchanged. I did this so that I can also control the hood manually via Home Assistant.

The following picture is finished device that is mounted in the hood itself. On the left side, there is a micro USB connector to power the microcontroller and an IR LED. On the right side is the IR receiver.

Automation Logic

In this configuration, the primary logic resides within the Hob2Hood functionality, which is beyond my direct control. My code’s sole purpose is to accurately translate the incoming commands into a format recognizable by the hood.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#include <IRsend.h>
#include <iostream>
#include "config.h"

IRrecv irrecv(RECV_PIN);
IRsend irsend(IR_LED);  // Set the GPIO to be used to sending the message.

// IR commands from AEG hob2hood device
const uint32_t IRCMD_VENT_1 = 0xE3C01BE2;     //Hob2hood On (level 1)
const uint32_t IRCMD_VENT_2 = 0xD051C301;     //Hob2hood level 2
const uint32_t IRCMD_VENT_3 = 0xC22FFFD7;     //Hob2hood level 3
const uint32_t IRCMD_VENT_4 = 0xB9121B29;     //Hob2hood level 4
const uint32_t IRCMD_VENT_OFF = 0x55303A3;    //Hob2hood off
const uint32_t IRCMD_LIGHT_ON = 0xE208293C;   //Light on (Hood on)
const uint32_t IRCMD_LIGHT_OFF = 0x24ACF947;  //Light off (Automatic after 2min)

// Faber hood codes
uint16_t faber_power[] = {868,606,816,1296,1534,636,818,614,816,1296,1534,2000,818,1296,818,612,1540};
uint16_t faber_light[] = {862, 614, 780, 676, 1502, 1322, 808, 622, 810, 646, 1504, 2684, 808, 622, 808, 648, 2228};
uint16_t faber_intense[] = {872, 604, 1538, 1312, 820, 612, 820, 610, 1538, 1312, 846, 1948, 1562, 1968, 1542};
uint16_t faber_up[] = {842, 634, 2258, 652, 814, 616, 816, 618, 2282, 626, 812, 2000, 2256, 1332, 1540};
uint16_t faber_down[] = {836, 1322, 1556, 614, 784, 646, 810, 1302, 1526, 642, 810, 2666, 1558, 1294, 1532};


//status vars
int light = 0;
int last_light = 0;
int current_vent = 0;
int target_vent = 0;

decode_results results;

void to_faber(uint16_t signal_data[]) {
  irsend.sendRaw(signal_data, sizeof(signal_data)/sizeof(signal_data[0]), 38);  // Send a raw data capture at 38kHz.
}

void setup(void){
  Serial.begin(115200);
  irrecv.enableIRIn();  // Start the receiver
  irsend.begin(); // Start IR sender
  while (!Serial)  // Wait for the serial connection to be establised.
    delay(50);
  Serial.println();
  Serial.print("IRrecvDemo is now running and waiting for IR message on Pin ");
  Serial.println(RECV_PIN);
  to_faber(faber_power);
}

void loop() {
  if (irrecv.decode(&results)) {
    switch (results.value) {
      case IRCMD_LIGHT_ON:
        light = 1;
        break;
        
      case IRCMD_LIGHT_OFF:
        light = 0;
        break;

      case IRCMD_VENT_1:
        target_vent = 1;
        break;

      case IRCMD_VENT_2:
        target_vent = 2;
        break;

      case IRCMD_VENT_3:
        target_vent = 3;
        break;

      case IRCMD_VENT_4:
        target_vent = 4;
        break;

      case IRCMD_VENT_OFF:
        target_vent = 0;
        break;

      default:
        break;
    }
    controlHood();
    irrecv.resume();
        
  }
}


void controlHood() {

  bool logLight = light!=last_light;
  bool logVent = target_vent!=current_vent;
  
  // control light
  switch (light) {
    // Light OFF
    case 0:
      if (logLight) {
        Serial.println("Light: OFF");
        irsend.sendRaw(faber_light, sizeof(faber_light)/sizeof(faber_light[0]), 38);
        delay(10);
      };
      
      break;
    // Light ON
    case 1:
      if (logLight) {
        Serial.println("Light: ON");
        irsend.sendRaw(faber_light, sizeof(faber_light)/sizeof(faber_light[0]), 38);
        delay(10);
      };
  };

  if (logVent) {
    while(current_vent != target_vent) {
      if (current_vent < target_vent) {
        if (current_vent == 0) {
          Serial.println("\nTurning ON\n");
          irsend.sendRaw(faber_power, sizeof(faber_power)/sizeof(faber_power[0]), 38);
          current_vent = 1;
        } else if (target_vent == 4) {
            Serial.println("\nTurning TURBO (lvl 4)\n");
            irsend.sendRaw(faber_intense, sizeof(faber_intense)/sizeof(faber_intense[0]), 38);
            current_vent = 4;
        } else {
            Serial.println("\nVent UP\n");
            irsend.sendRaw(faber_up, sizeof(faber_up)/sizeof(faber_up[0]), 38);
            current_vent++;
        };
      };
      
      if (current_vent > target_vent) {
        if (target_vent == 0) {
          Serial.println("\nTurning OFF\n");
          irsend.sendRaw(faber_power, sizeof(faber_power)/sizeof(faber_power[0]), 38);
          current_vent = 0;
        } else {
            Serial.println("\nVent DOWN\n");
            irsend.sendRaw(faber_down, sizeof(faber_down)/sizeof(faber_down[0]), 38);
            current_vent--;
        };
      };
      delay(300);
    };
  };

  last_light = light;
  
};