Things used in this project

Hardware components:
Thebase 97044185 8470 483f 8e2d 764c8d13dad0 grande
Modulo Base
×1
Thecontroller e8d08231 4c27 40d1 a660 46968bc162aa grande
Modulo Controller
×1
Thedisplay 569619b4 4aa8 473d 8480 737fd4600717 grande
Modulo Display (for Modulo)
×2
Theknob b7c2a1a3 69ea 4ce2 b565 7909a31f1f81 grande
Modulo Knob (for Modulo)
×1
IoT Power Relay
×1
10167 01
DHT22 Temperature Sensor
×1
Software apps and online services:
Ide web
Arduino IDE
Required Libraries: Adafruit DHT Unified, Adafruit Unified Sensor, DHT sensor library, LinkedList (https://github.com/ivanseidel/LinkedList), Modulo.

Code

PersonalThermostat.inoArduino
/*
 PersonalThermostat.ino - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#include "Modulo.h"
#include "Wire.h"

//#include "Mode.C"
#include "Sensor.C"
#include "Relay.C"
#include "UI.C"
#include "UiItem.C"
#include "UiColor.C"

const int SENSOR_PIN = 0;
const int RELAY_PIN = 4;
const unsigned long SENSOR_UPDATE_INTERVAL_MILLIS = 2000;
const unsigned long DISPLAY_UPDATE_INTERVAL_MILLIS = 50;
const float DEFAULT_TARGET_TEMP = 72.0;
const float DEFAULT_HYSTERESIS = 1.0;

const UiColor COLOR_TEMP  = UiColor(1.0, 0.9, 0.5);
const UiColor COLOR_HUMID = UiColor(0.7, 1.0, 0.9);
const UiColor COLOR_PARAM = UiColor(0.5, 0.5, 0.7);
const UiColor COLOR_FOCUS = UiColor(0.9, 0.7, 0.2);

//const Mode::Enum DEFAULT_MODE = Mode::Enum::COOL;
//Mode::Enum mode;
enum Mode { OFF, COOL, HEAT, ON };
const Mode DEFAULT_MODE = Mode::COOL;
Mode mode;

enum ParameterFocus { MODE, TRIP_ON, TRIP_OFF };
const ParameterFocus DEFAULT_PARAMETER_FOCUS = ParameterFocus::TRIP_ON;
ParameterFocus parameterFocus = DEFAULT_PARAMETER_FOCUS;

float targetTemp = DEFAULT_TARGET_TEMP;
float hysteresis = DEFAULT_HYSTERESIS;

Sensor sensor(SENSOR_PIN);
Relay relay(RELAY_PIN);
UI ui;
UiItem* tempItem;
UiItem* humidItem;
UiItem* tripOnItem;
UiItem* tripOnSignItem;
UiItem* tripOffItem;
UiItem* tripOffSignItem;
UiItem* modeItem;

int knobPositionPrevious;

unsigned long last_sensor_update_millis;
long time_since_last_sensor_update;

float getTripOnTemp()
  {
  return targetTemp;
  }

float getTripOffTemp()
  {
  float result = targetTemp - hysteresis;
  if (mode == Mode::HEAT)
    {
    result = targetTemp + hysteresis;
    }
  return result;
  }

void updateRelay()
  {
  switch (mode)
    {
    case Mode::OFF:
      if (relay.isOn())
        {
        relay.set(false);
        }
      break;

    case Mode::COOL:
      if (relay.isOn())
        {
        if (sensor.getTemperatureF() < getTripOffTemp())
          {
          relay.set(false);
          }
        }
      else // relay is off
        {
        if (sensor.getTemperatureF() >= getTripOnTemp())
          {
          relay.set(true);
          }
        }
      break;

    case Mode::HEAT:
      if (relay.isOn())
        {
        if (sensor.getTemperatureF() > getTripOffTemp())
          {
          relay.set(false);
          }
        }
      else // relay is off
        {
        if (sensor.getTemperatureF() <= getTripOnTemp())
          {
          relay.set(true);
          }
        }
      break;

    case Mode::ON:
      if (!relay.isOn())
        {
        relay.set(true);
        }
      break;
    }
    
  ui.setIndicator(2, relay.isOn());
  }

String modeToString(Mode mode_)
  {
  String result;
  switch (mode_)
    {
    case Mode::OFF:  result = String("Off"); break;
    case Mode::COOL: result = String("Cool"); break;
    case Mode::HEAT: result = String("Heat"); break;
    case Mode::ON:   result = String("On"); break;
    }
  return result;
  }

Mode nextMode(Mode mode_)
  {
  Mode result;
  switch (mode_)
    {
    case Mode::OFF:  result = Mode::COOL; break;
    case Mode::COOL: result = Mode::HEAT; break;
    case Mode::HEAT: result = Mode::ON; break;
    case Mode::ON:   result = Mode::OFF; break;
    }
  return result;
  }

Mode previousMode(Mode mode_)
  {
  Mode result;
  switch (mode_)
    {
    case Mode::OFF:  result = Mode::ON; break;
    case Mode::COOL: result = Mode::OFF; break;
    case Mode::HEAT: result = Mode::COOL; break;
    case Mode::ON:   result = Mode::HEAT; break;
    }
  return result;
  }

ParameterFocus nextParameterFocus(ParameterFocus parameterFocus_)
  {
  ParameterFocus result;
  switch(parameterFocus_)
    {
    case ParameterFocus::MODE:     result = ParameterFocus::TRIP_ON; break;
    case ParameterFocus::TRIP_ON:  result = ParameterFocus::TRIP_OFF; break;
    case ParameterFocus::TRIP_OFF: result = ParameterFocus::MODE; break;
    }
  return result;
  }

void updateUIforMode()
  {
  modeItem->setText(modeToString(mode));
  switch (mode)
    {
    case Mode::OFF:
      ui.setKnobColor(UiColor::BLACK);
      tripOnSignItem->setVisible(false);
      tripOnItem->setVisible(false);
      tripOffSignItem->setVisible(false);
      tripOffItem->setVisible(false);
      updateTripItems();
      break;

    case Mode::COOL:
      ui.setKnobColor(UiColor::BLUE);
      tripOnSignItem->setVisible(true);
      tripOnSignItem->setText(String(">= "));
      tripOnItem->setVisible(true);
      tripOffSignItem->setVisible(true);
      tripOffSignItem->setText(String("< "));
      tripOffItem->setVisible(true);
      updateTripItems();
      break;

    case Mode::HEAT:
      ui.setKnobColor(UiColor::RED);
      tripOnSignItem->setVisible(true);
      tripOnSignItem->setText(String("<= "));
      tripOnItem->setVisible(true);
      tripOffSignItem->setVisible(true);
      tripOffSignItem->setText(String("> "));
      tripOffItem->setVisible(true);
      updateTripItems();
      break;

    case Mode::ON:
      ui.setKnobColor(UiColor::WHITE);
      tripOnSignItem->setVisible(false);
      tripOnItem->setVisible(false);
      tripOffSignItem->setVisible(false);
      tripOffItem->setVisible(false);
      updateTripItems();
      break;
    }
  }

void setMode(Mode mode_)
  {
  mode = mode_;
  updateUIforMode();
  }

void onKnobButtonRelease(KnobModulo& knob_)
  {
  parameterFocus = nextParameterFocus(parameterFocus);
  }

void updateTripItems()
  {
  tripOnItem->setText(String(getTripOnTemp(), 1));
  tripOffItem->setText(String(getTripOffTemp(), 1));
  }

void onKnobPositionChange(KnobModulo& knob_)
  {
  int knobPositionCurrent = knob_.getPosition();
  int knobPositionDelta = knobPositionCurrent - knobPositionPrevious;
  knobPositionPrevious = knobPositionCurrent;
  switch (parameterFocus)
    {
    case ParameterFocus::MODE:
      if (knobPositionDelta < 0)
        {
        setMode(previousMode(mode));
        }
      else
        {
        setMode(nextMode(mode));
        }
      break;
    
    case ParameterFocus::TRIP_ON:
      if (mode == Mode::OFF || mode == Mode::ON) return;
      targetTemp += (knobPositionDelta / 10.0);
      updateTripItems();
      break;

    case ParameterFocus::TRIP_OFF:
      if (mode == Mode::OFF || mode == Mode::ON) return;
      if (mode == Mode::COOL)
        {
        hysteresis -= (knobPositionDelta / 10.0);
        }
      else if (mode == Mode::HEAT)
        {
        hysteresis += (knobPositionDelta / 10.0);
        }
      if (hysteresis < 0.1) hysteresis = 0.1;
      updateTripItems();
      break;
    }
  }

void initUI()
  {
  ui.initialize();

             ui.item(1)->text("Temperature ")->position(0, 0)  ->color(COLOR_TEMP);
  tempItem = ui.item(1)->text("(temp)")      ->position(20, 13)->textSize(2);
             ui.item(1)->text("F");
  
              ui.item(1)->text("Humidity ")->position(0, 32) ->color(COLOR_HUMID);
  humidItem = ui.item(1)->text("(humid)")  ->position(20, 45)->textSize(2);
              ui.item(1)->text("%");

             ui.item(2)->text("Mode ") ->position(0,  0)->color(COLOR_PARAM);
  modeItem = ui.item(2)->text("(mode)")->textSize(2);

                   ui.item(2)->text("On ")->position(0, 20)->color(COLOR_PARAM);
  tripOnSignItem = ui.item(2)->text("(onSign)");
      tripOnItem = ui.item(2)->text("(onTemp)")->textSize(2);
                   ui.item(2)->text("F");
  
                    ui.item(2)->text("Off ")     ->position(0, 40)->color(COLOR_PARAM);
  tripOffSignItem = ui.item(2)->text("(offSign)");
      tripOffItem = ui.item(2)->text("(offTemp)")->textSize(2);
                    ui.item(2)->text("F");
  
  tempItem->setText(String(sensor.getTemperatureF(), 1));
  humidItem->setText(String(sensor.getRHumidity(), 1));
  tripOnItem->setText(String(getTripOnTemp(), 1));
  tripOffItem->setText(String(getTripOffTemp(), 1));
  updateUIforMode();

  ui.setKnobColor(COLOR_FOCUS);
  ui.setKnobButtonReleaseCallback(onKnobButtonRelease);
  ui.setKnobPositionChangeCallback(onKnobPositionChange);
  }

void updateUI()
  {
  UiColor color;
  
  color = COLOR_PARAM;
  if (parameterFocus == ParameterFocus::MODE) color = COLOR_FOCUS;
  modeItem->setColor(color);
  
  color = COLOR_PARAM;
  if (parameterFocus == ParameterFocus::TRIP_ON) color = COLOR_FOCUS;
  tripOnItem->setColor(color);
  
  color = COLOR_PARAM;
  if (parameterFocus == ParameterFocus::TRIP_OFF) color = COLOR_FOCUS;
  tripOffItem->setColor(color);
  
  ui.update();
  }

void updateSensor()
  {
  ui.setIndicator(1, true);
  sensor.update();
  last_sensor_update_millis = millis();
  ui.setIndicator(1, false);
  tempItem->setText(String(sensor.getTemperatureF(), 1));
  humidItem->setText(String(sensor.getRHumidity(), 1));
  }

void setup()
  {
  delay(1000);  // give bootloader a chance!
  sensor.initialize();
  relay.initialize();
  initUI();
  setMode(DEFAULT_MODE);
  updateSensor();
  updateRelay();
  updateUI();
  }

void loop()
  {
  time_since_last_sensor_update = millis() - last_sensor_update_millis;
  if (time_since_last_sensor_update >= SENSOR_UPDATE_INTERVAL_MILLIS)
    {
    updateSensor();
    updateRelay();
    }
  updateUI();
  ui.loop();
  delay(DISPLAY_UPDATE_INTERVAL_MILLIS);
  }
Relay.CC/C++
/*
 Relay.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

#include "Wire.h"

class Relay
  {
 public:

  Relay(int pin_)
    {
    _pin = pin_;
    _on = false;
    }

  void initialize()
    {
    pinMode(_pin, OUTPUT);
    }

  bool isOn()
    {
    return _on;
    }

  void set(bool on_)
    {
    if (on_)
      {
      digitalWrite(_pin, HIGH);
      _on = true;
      }
    else
      {
      digitalWrite(_pin, LOW);
      _on = false;
      }
    }

 private:
  int _pin;
  bool _on;

  }; // class Relay
Sensor.CC/C++
/*
 Sensor.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

const uint8_t DHT_TYPE = DHT22;

class Sensor
  {
 public:

  Sensor(int pin_)
    :
    _dht(pin_, DHT_TYPE)
    {
    }

  float getRHumidity()
    {
    return _humid;
    }

  float getTemperatureF()
    {
    return _tempF;
    }

  void initialize()
    {
    _dht.begin();
    }

  void update()
    {
    sensors_event_t event;
    _dht.temperature().getEvent(&event);
    float tempC = event.temperature;
    if (isnan(tempC))
      {
      _tempF = tempC;
      }
    else
      {
      _tempF = (event.temperature * 1.8) + 32;
      }
    _dht.humidity().getEvent(&event);
    _humid = event.relative_humidity;
    }

 private:

  DHT_Unified _dht;
  float _tempF;
  float _humid;

  }; // class Sensor
UI.CC/C++
/*
 UI.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

#include "Modulo.h"
#include "Wire.h"
#include <LinkedList.h>
#include "UiItem.C"
#include "UiColor.C"
#include "UiPosition.C"

class UI
  {
 public:

  UI()
    :
    _display1(),
    _display2(),
    _knob()
    {
    }

  UiItem* item(int n_)
    {
    UiItem* newItem = new UiItem();
    if (n_ == 1)
      {
      _items1.add(newItem);
      }
    else if (n_ == 2)
      {
      _items2.add(newItem);
      }
    return newItem;
    }

  void setIndicator(int n_, bool on_)
    {
    if (n_ <= 0 || n_ > 3) return;
    uint16_t deviceID;
    switch(n_)
      {
      case 1: deviceID = _display1.getDeviceID(); break;
      case 2: deviceID = _display2.getDeviceID(); break;
      case 3: deviceID = _knob.getDeviceID(); break;
      }
    ModuloStatus status = ModuloStatus::ModuloStatusOff;
    if (on_) status = ModuloStatus::ModuloStatusOn;
    Modulo.setStatus(deviceID, status);
    }

  void setKnobColor(const UiColor& color)
    {
    _knob.setColor(color.getRed(), color.getGreen(), color.getBlue());
    }

  void setKnobPositionChangeCallback(void (*callback_)(KnobModulo&))
    {
    _knob.setPositionChangeCallback(callback_);
    }

  void setKnobButtonReleaseCallback(void (*callback_)(KnobModulo&))
    {
    _knob.setButtonReleaseCallback(callback_);
    }

  void drawItem(DisplayModulo& display_, UiItem* item_)
    {
    if (!item_->isVisible()) return;
    UiPosition* pPosition = item_->getPosition();
    if (pPosition->isSet())
      {
      display_.setCursor(pPosition->getX(), pPosition->getY());
      }
    UiColor* pColor = item_->getColor();
    if (pColor->isSet())
      {
      display_.setTextColor(pColor->getRed(),
                            pColor->getGreen(),
                            pColor->getBlue());
      }
    display_.setTextSize(item_->getTextSize());
    display_.print(item_->getText());
    }

  void initialize()
    {
    Modulo.setup();
    for (int n = 1; n <= 3; n++)
      {
      for (int i = 1; i <= 3; i++)
        {
        setIndicator(i, true);
        delay(100);
        setIndicator(i, false);
        }
      }
    }

  void update()
    {
    updateDisplay(_display1, _items1);
    updateDisplay(_display2, _items2);
    }

  void updateDisplay(DisplayModulo& display_, LinkedList<UiItem*>& items_)
    {
    display_.clear();
    for (int i = 0; i < items_.size(); i++)
      {
      UiItem* e = items_.get(i);
      drawItem(display_, e);
      }
    display_.refresh();
    }

  void loop()
    {
    Modulo.loop();
    }

 private:
  DisplayModulo _display1;
  DisplayModulo _display2;
  KnobModulo _knob;
  LinkedList<UiItem*> _items1;
  LinkedList<UiItem*> _items2;

  }; // end class UI
UiColor.CC/C++
/*
 UiColor.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

class UiColor
  {
 public:
  
  UiColor(float red_, float green_, float blue_)
    {
    _set = true;
    _red = red_;
    _green = green_;
    _blue = blue_;
    }

  UiColor()
    {
    _set = false;
    _red = NAN;
    _green = NAN;
    _blue = NAN;
    }

  UiColor(const UiColor& color_)
    {
    _set = color_.isSet();
    _red = color_.getRed();
    _green = color_.getGreen();
    _blue = color_.getBlue();
    }

  UiColor(UiColor* pColor_)
    {
    _set = pColor_->isSet();
    _red = pColor_->getRed();
    _green = pColor_->getGreen();
    _blue = pColor_->getBlue();
    }

  float getRed() const { return _red; }
  float getGreen() const { return _green; }
  float getBlue() const { return _blue; }
  bool isSet() const { return _set; }

  static const UiColor NOT_SET;
  static const UiColor BLACK;
  static const UiColor WHITE;
  static const UiColor RED;
  static const UiColor GREEN;
  static const UiColor BLUE;

 private:
 
  bool _set;
  float _red;
  float _green;
  float _blue;

  }; // end class UiColor
  
const UiColor UiColor::NOT_SET  = new UiColor();
const UiColor UiColor::BLACK = new UiColor(0.0, 0.0, 0.0);
const UiColor UiColor::WHITE = new UiColor(1.0, 1.0, 1.0);
const UiColor UiColor::RED   = new UiColor(1.0, 0.0, 0.0);
const UiColor UiColor::GREEN = new UiColor(0.0, 1.0, 0.0);
const UiColor UiColor::BLUE  = new UiColor(0.0, 0.0, 1.0);
UiItem.CC/C++
/*
 UiItem.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

#include "UiColor.C"
#include "UiPosition.C"

class UiItem
  {
 public:

  UiItem(const UiPosition& position_, const UiColor& color_, int textSize_, const String& text_)
    {
    _pPosition = new UiPosition(position_);
    _pColor = new UiColor(color_);
    _textSize = textSize_;
    _pText = new String(text_);
    _visible = true;
    }

  UiItem(const UiPosition& position_, const UiColor& color_, int textSize_, const char* charString_)
    {
    _pPosition = new UiPosition(position_);
    _pColor = new UiColor(color_);
    _textSize = textSize_;
    _pText = new String(charString_);
    _visible = true;
    }

  UiItem(const UiItem& other_)
    {
    _pPosition = new UiPosition(other_.getPosition());
    _pColor = new UiColor(other_.getColor());
    _textSize = other_.getTextSize();
    _pText = new String(other_.getText());
    _visible = other_.isVisible();
    }

  UiItem()
    {
    _pPosition = new UiPosition(DEFAULT_POSITION);
    _pColor = new UiColor(DEFAULT_COLOR);
    _textSize = DEFAULT_TEXTSIZE;
    _pText = new String(DEFAULT_TEXT);
    _visible = DEFAULT_VISIBLE;
    }

  UiPosition* getPosition() const { return _pPosition; }
  UiItem* position(const UiPosition& position_)
    {
    if (_pPosition) delete _pPosition;
    _pPosition = new UiPosition(position_);
    return this;
    }
  UiItem* position(int x_, int y_)
    {
    if (_pPosition) delete _pPosition;
    _pPosition = new UiPosition(x_, y_);
    return this;
    }
  void setPosition(const UiPosition& position_)
    {
    position(position_);
    }
  void setPosition(int x_, int y_)
    {
    position(x_, y_);
    }
  
  UiColor* getColor() const { return _pColor; }
  UiItem* color(const UiColor& color_)
    {
    if (_pColor) delete _pColor;
    _pColor = new UiColor(color_);
    return this;
    }
  void setColor(const UiColor& color_)
    {
    color(color_);
    }

  int getTextSize() const { return _textSize; }
  UiItem* textSize(int textSize_)
    {
    _textSize = textSize_;
    return this;
    }
  void setTextSize(int textSize_)
    {
    textSize(textSize_);
    }

  String getText() const { return *_pText; }
  UiItem* text(const String& text_)
    {
    if (_pText) delete _pText;
    _pText = new String(text_);
    return this;
    }
  void setText(const String& text_)
    {
    text(text_);
    }

  boolean isVisible() const { return _visible; }
  UiItem* setVisible(bool visible_)
    {
    _visible = visible_;
    return this;
    }

 private:

  const UiPosition DEFAULT_POSITION = UiPosition::NOT_SET;
  const UiColor DEFAULT_COLOR = UiColor::NOT_SET;
  const int DEFAULT_TEXTSIZE = 1;
  const String DEFAULT_TEXT = String("?");
  const bool DEFAULT_VISIBLE = true;

  UiPosition* _pPosition;
  UiColor* _pColor;
  int _textSize;
  String* _pText;
  bool _visible;

  }; // end class UiItem
UiPosition.CC/C++
/*
 UiPosition.C - Personal Thermostat project
 Copyright (C) 2016 Andy Moore.  All rights reserved.

 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 3 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.
*/

#pragma once

class UiPosition
  {
 public:
  
  UiPosition(int x_, int y_)
    {
    _set = true;
    _x = x_;
    _y = y_;
    }

  UiPosition()
    {
    _set = false;
    }

  UiPosition(const UiPosition& position_)
    {
    _set = position_.isSet();
    _x = position_.getX();
    _y = position_.getY();
    }

  UiPosition(UiPosition* pPosition_)
    {
    _set = pPosition_->isSet();
    _x = pPosition_->getX();
    _y = pPosition_->getY();
    }

  int getX() const { return _x; }
  int getY() const { return _y; }
  bool isSet() const { return _set; }

  static const UiPosition NOT_SET;

 private:
 
  bool _set;
  int _x;
  int _y;

  }; // end class UiPosition
  
const UiPosition UiPosition::NOT_SET = new UiPosition();

Credits

66f9d585eaf9717bead8b2fdc791a232
Andy Moore
1 project • 3 followers
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog