Eden powered by HomeGenie

Programmable Wi-Fi Thermostat and Universal IR Controller

Eden is a DIY project based on HomeGenie software and Eden Sensor Board, a Multipurpose Sensor Board for Raspberry Pi.
Its main purpose is to implement a programmable wi-fi thermostat and universal IR transceiver, but also other functionalities can be easily added by using various connectors and a small prototype area available on the board.

Component Listing

Features you'll get out of the box

  • Temperature and Luminance sensing
  • Programmable IR transceiver for controlling AC/AV and other IR controllable devices
  • External enviroment data sensing (using third party internet service)
  • "Wizard" scripting for creating scenarios and other automation tasks
  • Builtin statistics, user interface and automation engine powered by HomeGenie
  • Modular and expandible hardware system (see Eden Board specifications below)
  • Web Service API
  • Web based IDE with a friendly user interface for easy GPIO/I2C/SPI/UART/Arduino™ programming, using your favourite language (C#, Javascript, Python, Ruby)

About Eden Sensor Board

We can choose between two models of this board. The first one (v1) is based on MCP3008 ADC, while the second one (v2) is based on Arduino™ Pro Mini 3V.
Click on the link below to find out more:

SSD1306 OLED Display with control buttons

SSD1306 is a cheap OLED display that can be connected to Raspberry Pi I2C port (or Arduino I2C if you are using Eden V2).
By also adding 4 buttons, we can create a menu on the display and navigate/control the various options by using the buttons.
These are connected with one end to the 3V3, and the other end to GPIO#22, GPIO#23, GPIO#24, GPIO#25. Also the internal pull-down resistor is enabled on these pins.
The video below will show how to setup all of this in few steps with HomeGenie:


The program that control the menu and the navigation with the 4 buttons is entirely written in Javascript! This program source code is included in HomeGenie and can be customized by using built-in HomeGenie Program Editor.
To get started with HomeGenie automation programming see Automation Programming Introduction.
Just to give you an idea on how easy it is, we are posting its code below (hopefully at this point you already know how automation programming works in HomeGenie =)):

// Get a reference to the OLED object
var oled = hg.Modules.InDomain("Components.Ssd1306").WithAddress("0");

// Get a reference to other programs of which data will be displayed on the OLED screen
var thermostat = hg.Modules.WithName("Generic Thermostat").Get();
var setPoint = thermostat.Parameter("Thermostat.SetPoint.Heating");
var securitySystem = hg.Modules.WithName("Security Alarm System").Get();
var securityArmed = securitySystem.Parameter("HomeGenie.SecurityArmed");

// Global state variables
var currentContext = '';
var displayMode = 'normal';
var lastButton = '';
var startPressTs = new Date().getTime();
// This system wide parameter is used to prevent other apps
// from writing on the OLED screen  when the menu is open
hg.Settings.Parameter('EdenDisplay.MenuMode').Value = 'OFF';

// Menu screens

function menuShowMain()
{
  oled.Command("Oled.GoTo").Execute("0/3");
  oled.Command("Oled.DrawText").Execute("----[ MENU ]----");
  oled.Command("Oled.GoTo").Execute("0/4");
  oled.Command("Oled.DrawText").Execute("1 Set Point/LEFT");
  oled.Command("Oled.GoTo").Execute("0/5");
  oled.Command("Oled.DrawText").Execute("2 Security/LEFT");
  oled.Command("Oled.GoTo").Execute("0/6");
  oled.Command("Oled.DrawText").Execute("3 Invert Display/LEFT");
  oled.Command("Oled.GoTo").Execute("0/7");
  oled.Command("Oled.DrawText").Execute("4 Exit/LEFT");
}

function menuShowSetPoint()
{
  oled.Command("Oled.GoTo").Execute("0/3");
  oled.Command("Oled.DrawText").Execute("/LEFT");
  oled.Command("Oled.GoTo").Execute("0/4");
  oled.Command("Oled.DrawText").Execute("Set Point:/LEFT");
  oled.Command("Oled.GoTo").Execute("0/5");
  oled.Command("Oled.DrawText2").Execute(setPoint.Value + "/CENTER");
  oled.Command("Oled.GoTo").Execute("0/7");
  oled.Command("Oled.DrawText").Execute("2 + 3 -   EXIT 4/CENTER");  
}

function menuShowSecurity()
{
  var level = securitySystem.Parameter("Status.Level");
  oled.Command("Oled.GoTo").Execute("0/3");
  oled.Command("Oled.DrawText").Execute("/LEFT");
  oled.Command("Oled.GoTo").Execute("0/4");
  oled.Command("Oled.DrawText").Execute("Security:/LEFT");
  oled.Command("Oled.GoTo").Execute("0/5");
  oled.Command("Oled.DrawText2").Execute((securityArmed.DecimalValue > 0 || level.DecimalValue > 0 ? "ARMED" : "DISARMED") + "/CENTER");
  oled.Command("Oled.GoTo").Execute("0/7");
  if (securityArmed.DecimalValue > 0 || level.DecimalValue > 0)
  {
    oled.Command("Oled.DrawText").Execute("2 DISARM  EXIT 4/CENTER");
  }
  else
  {
    oled.Command("Oled.DrawText").Execute("2 ARM     EXIT 4/CENTER");
  }
}

// Context switch functions

function setContext(ctx)
{
  currentContext = ctx;
  hg.Settings.Parameter('EdenDisplay.MenuMode').Value = 'ON';
  switch(ctx)
  {
    case 'main':
      menuShowMain();
      break;
    case 'setpoint':
      menuShowSetPoint();
      break;
    case 'security':
      menuShowSecurity();
      break;
    case 'energysaving':
      menuShowEnergySaving();
      break;
    case 'exit':
      oled.Command("Oled.GoTo").Execute("0/3");
      oled.Command("Oled.DrawText").Execute("/CENTER");
      oled.Command("Oled.GoTo").Execute("0/4");
      oled.Command("Oled.ShowLogo").Execute();
      hg.Pause(2);
      hg.Settings.Parameter('EdenDisplay.MenuMode').Value = 'OFF';
      break;
  }
}

function setContextInput(input)
{
  switch (input)
  {
    case '1': // BUTTON #1
      switch (currentContext)
      {
        case 'main':
          setContext('setpoint');
          break;
      }
      break;
    case '2': // BUTTON #2
      switch (currentContext)
      {
        case 'main':
          setContext('security');
          break;
        case 'setpoint':
          thermostat.Command("Thermostat.SetPointSet").Execute("Heating/" + (setPoint.DecimalValue + 1));
          menuShowSetPoint();
          break;
        case 'security':
          if (securityArmed.DecimalValue == 0)
          {
            securitySystem.Command("Control.On").Execute();
          }
          else
          {
            securitySystem.Command("Control.Off").Execute();
          }
          menuShowSecurity();
          break;
      }
      break;
    case '3': // BUTTON #3
      switch (currentContext)
      {
        case 'main':
          if (displayMode == 'normal')
          {
            displayMode = 'inverse';
            oled.Command("Oled.DisplayInvert").Execute();
          }
          else
          {
            displayMode = 'normal';
            oled.Command("Oled.DisplayNormal").Execute();
          }
          break;
        case 'setpoint':
          thermostat.Command("Thermostat.SetPointSet").Execute("Heating/" + (setPoint.DecimalValue - 1));
          menuShowSetPoint();
          break;
      }
      break;
    case '4': // BUTTON #4
      switch (currentContext)
      {
        case 'main':
          setContext('exit');
          break;
        default:
          setContext('main');
          break;
      }
      break;
  }

}

hg.When.ModuleParameterChange(function(module, parameter){
  if (module.Instance.Domain == 'RaspberryPi.Gpio' && parameter.Is("Status.Level") && parameter.DecimalValue > 0)
  {
    // A button was pressed, store the timestamp
    startPressTs = new Date().getTime();
    if (currentContext == '')
    {
      // A long press of 3 seconds will open the settings menu
      var duration = 0;
      while (duration < 3 && parameter.DecimalValue > 0)
      {
          hg.Pause(1);
          duration++;
      }
      if (duration >= 3) setContext('main');
      return true;
    }
    //
    // The input is only processed when the settings menu is opened
    switch (module.Instance.Address)
    {
        // BUTTON #1 pressed
      case 'GPIO22': 
        setContextInput('1');
        break;
        // BUTTON #2 pressed
      case 'GPIO23':
        setContextInput('2');
        break;
        // BUTTON #3 pressed
      case 'GPIO24':
        setContextInput('3');
        break;
        // BUTTON #4 pressed
      case 'GPIO25':
        setContextInput('4');
        break;
    }
  }
  else if (module.Instance.Domain == 'RaspberryPi.Gpio' && parameter.Is("Status.Level") && parameter.DecimalValue == 0)
  {
    // A button was released
    var currentTs = new Date().getTime();
    if (currentContext == 'exit')
    {
      currentContext = '';
    }
    else if (currentContext == '' && currentTs - startPressTs < 3000) // 3 seconds
    {
      // We are outside the settings menu, so
      // the buttons functionality is to toggle scenarios/devices
      lastButton = '';
      switch (module.Instance.Address)
      {
          // BUTTON #1 released
        case 'GPIO22': 
          lastButton = '1';
          break;
          // BUTTON #2 released
        case 'GPIO23': 
          lastButton = '2';
          break;
          // BUTTON #3 released
        case 'GPIO24': 
          lastButton = '3';
          break;
          // BUTTON #4 released
        case 'GPIO25':
          lastButton= '4';
          break;
      }
      if (lastButton != '')
      {
        hg.Modules.WithFeature("EdenDisplay.ToggleButton." + lastButton).Toggle();
        var program = hg.Program.InputField("EdenDisplay.ButtonProgram." + lastButton).Value;
        // scenarios are specified in the form /
        if (program != '')
        {
          // it is a scenario
          var options = '';
          if (program.lastIndexOf('/') > 0) 
          {
            options = program.substring(program.lastIndexOf('/') + 1);
            program = program.substring(0, program.lastIndexOf('/'));
          }
          hg.Program.Run(program, options);
        }
      }
    }
    // Reset long press timestamp
    startPressTs = new Date().getTime();
  }
  else if (parameter.Is("HomeGenie.SecurityArmed") && currentContext == "security")
  {
    // update security menu
    menuShowSecurity();
  }
  return true;
});

hg.Program.GoBackground();

 

If you find this project useful, please encourage its development by donating. Thank you! =)
Get it on Google Play

 

TOP

Do It Yourself!

If you find this project useful, please encourage its development by donating. Thank you! =)
Get it on Google Play

Lastest Topics

User's Guide