Al MargolisAnoja RajalakshmiAshokmhellar
Published © GPL3+

Smart Outlet to Reduce Peak Power Needs

Eliminate inefficient peak power generation by intelligently coordinating demand.

AdvancedShowcase (no instructions)Over 1 day2,265
Smart Outlet to Reduce Peak Power Needs

Things used in this project

Hardware components

uln2803
×1
DC motor (generic)
×1
LED (generic)
LED (generic)
×1
NeoPixel strip
NeoPixel strip
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1

Software apps and online services

Unity
Unity
Arduino IDE
Arduino IDE
AWS Lambda
Amazon Web Services AWS Lambda

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Laser cutter (generic)
Laser cutter (generic)
3D Printer (generic)
3D Printer (generic)

Story

Read more

Schematics

Flow Diagram for Node-Red

Github Repository

Code

index-mraa.js

JavaScript
var Edison = require("edison-io");

var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://ec2-35-161-110-220.us-west-2.compute.amazonaws.com')

var mraa = require('mraa');

const SmartOn = 'on'
const SmartOff = 'off'

const HouseName = "/Main110_"
var HouseTopic = HouseName + 'Controller'
var AcTopic = HouseName + 'Ac'
var HeaterTopic = HouseName + 'Heater'
var LightsTopic = HouseName + 'Lights'
var StoveTopic = HouseName + 'Stove'
var ThermostatTopic = HouseName + 'Thermostat'
var ClockTopic = HouseName + 'Clock'
var TopicList = [HouseTopic, AcTopic, HeaterTopic, LightsTopic, StoveTopic, ThermostatTopic, ClockTopic]

const AcLedPin		= 2
const MotorPin		= 6		// pwm
const HeaterLedPin	= 4
const HouseLightsPin	= 5		// pwm
const WashingMachinePin	= 9		// pwm
const StoveLedPin	= 10		// pwm

const PortTypeGpio = "g"
const PortTypePwm = "p"

function IoWrite(value) {
	console.log("IoWrite " + this.pin .toString() + ' --> ' + value.toString() + ' - MaxPwm: ' + this.maxPwm.toString());
	if (this.type === PortTypePwm) {
		if (value < 0.001) {
			value = 0.0;
			this.io.enable(true);
			this.io.write(0.2);
			this.io.write(0.1);
			this.io.write(0);
			this.lastValue = value;
			this.io.enable(false);
			this.enabled = false;
			console.log("ZERO FIX " + value.toString());
		} else {
			if (!this.enabled) {
				this.io.enable(true);
				this.enabled = true;
			};
			if (value > this.maxPwm) {
			       value = this.maxPwm;
			};	       
			this.io.write(value);
			this.lastValue = value;
		}
	} else {
		this.io.write(value);
		this.lastValue = value;
	};
}

function IoFadeStep(step) {
	if (step != undefined) {
		this.fadeStep = step;
	};
	if (this.fadeStep == undefined) {
		return;
	};
	this.lastValue = this.lastValue + this.fadeStep;
	if (this.fadeStep < 0) {
		if (this.lastValue < 0.0) {
			this.lastValue = 0.0;
			this.fadeStep = undefined;
		}
	} else {
		if (this.lastValue > 1.0) {
			this.lastValue = 1.0;
			this.fadeStep = undefined;
		}
	}
}

function IoPort(type, pin, isOutput) {
	this.lastValue = 0;
	this.fadeStep = undefined;
	this.type = type;
	this.pin = pin;
	this.maxPwm = 0.9;
	if (isOutput === undefined) {
		this.isOutput = true;
	} else if (isOutput) {
		this.isOutput = true;
	} else {
		this.isOutput = false;
	};
	if (this.type == PortTypePwm) {
		this.io = new mraa.Pwm(this.pin);
		this.io.enable(true);
		this.enabled = true;
	} else {
		this.io = new mraa.Gpio(this.pin);
		if (this.isOutput) {
			this.io.dir(mraa.DIR_OUT);
		} else {
			this.io.dir(mraa.DIR_IN);
		};
		this.enabled = true;
	}
	this.write = IoWrite;
	this.fade = IoFadeStep;
}

var AcLedGpio = new IoPort(PortTypeGpio, AcLedPin); 
var MotorPwm = new IoPort(PortTypeGpio, MotorPin);
MotorPwm.maxPwm = 0.2;
var HeaterLedGpio = new IoPort(PortTypeGpio, HeaterLedPin); 
var StoveLedGpio = new IoPort(PortTypeGpio, StoveLedPin); 
var HouseLightsPwm = new IoPort(PortTypePwm, HouseLightsPin);

client.on('connect', function() {
    client.subscribe(TopicList);
    client.publish(HouseTopic, SmartOn);
});

AcDevice(SmartOff);
HeaterDevice(SmartOff);
GpioDevice(StoveLedGpio, SmartOff);

function AcDevice(state) {
  if (state === SmartOn) {
    HeaterDevice(SmartOff);
    MotorPwm.write(1.0);
    AcLedGpio.write(1);
    console.log('AC ON');
    //client.publish(AcTopic, SmartOn);
  } else {
    MotorPwm.write(0.0);
    AcLedGpio.write(0);
    console.log('AC OFF');
    //client.publish(AcTopic, SmartOff);
  }
}

function HeaterDevice(state) {
  if (state === SmartOn) {
    AcDevice(SmartOff);
    MotorPwm.write(1.0);
    HeaterLedGpio.write(1);
    console.log('Heater Turned On' );
    //client.publish(HeaterTopic, SmartOn);
  } else {
    MotorPwm.write(0.0);
    HeaterLedGpio.write(0);
    console.log('Heater Turned Off' );
    //client.publish(HeaterTopic, SmartOff);
  }
}

function GpioDevice(gpio, state) {
  if (state === SmartOn) {
    gpio.write(1);
  } else {
    gpio.write(0);
  }
}

function PwmDevice(gpio, valueS) {
  valueF = parseFloat(valueS);
  console.log('PWM ' + valueF.toString());
  gpio.write(valueF);
}

client.on('message', function(topic, message) {
            // message is Buffer
	    thisTopic = topic.toString();
	    thisMessage = message.toString(); 
            console.log(thisTopic + ' : ' + thisMessage );
            if(thisTopic === AcTopic){
		AcDevice(thisMessage);
            }else if(thisTopic === HeaterTopic){
		HeaterDevice(thisMessage);
            }else if(thisTopic === StoveTopic){
		GpioDevice(StoveLedGpio, thisMessage);
            }else if(thisTopic === LightsTopic){
		PwmDevice(HouseLightsPwm, thisMessage);
            };
            client.publish(thisTopic+'_State', thisMessage);
    });

var interval = setInterval(function(str1, str2) {
	  console.log(str1 + " " + str2);
}, 1000, "Running.", "House Monitor Loop");

// clearInterval(interval);
//while (true) {
//  setTimeout(function () {
//	  console.log('boo')
//  }, 5000);
//}

Dashboard

JavaScript
Websocket Dashboard
<!DOCTYPE html>
<html>

<head>
    <title>Edison Connect</title>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.css" integrity="sha256-3AnlRNIdX11hf3yyjAb12b2Tac0VmZxGxpVRURyJIAw=" crossorigin="anonymous" />
    <script>
    var outgoing = "hi";
    var socket = io.connect('//localhost:3000');

    $(document).ready(function() {
        $("#target").click(function() {
                socket.emit('message', outgoing);
            });
        });

    socket.on('data', function(data) {
        console.log(data);
        dataIn = data.toString();
	fldCode = dataIn.substring(0,1);
	msgData = dataIn.substring(1);
	if (fldCode == 'T') {
          $('#ctlTime').text(msgData);
	} else if (fldCode == 'C') {
          $('#ctlTemp').text(msgData);
	} else if (fldCode == 'A') {
          $('#ctlAc').text(msgData);
	} else if (fldCode == 'H') {
          $('#ctlHeater').text(msgData);
	} else if (fldCode == 'L') {
          $('#ctlLights').text(msgData);
	} else if (fldCode == 'S') {
          $('#ctlStove').text(msgData);
	} else {
          $('#ctlXXX').text(dataIn);
	};
    }); socket.on('error', function() {
        console.error(arguments)
    }); 

    </script>
</head>

<body>
    <table>
      <tr><td>Time:</td><td><span id="ctlTime"></span></td></tr>
      <tr><td>Outside Temp:</td><td><span id="ctlTemp"></span></td></tr>
      <tr><td>Heater:</td><td><span id="ctlHeater"></span></td></tr>
      <tr><td>Air Conditioning:</td><td><span id="ctlAc"></span></td></tr>
      <tr><td>Lights:</td><td><span id="ctlLights"></span></td></tr>
      <tr><td>Stove:</td><td><span id="ctlStove"></span></td></tr>
      <tr><td>Unknown:</td><td><span id="ctlXXX"></span></td></tr>
    </table>

    <a class="waves-effect waves-light btn-large" id="target">Button</a>

</body>

</html>

MQTT Power Broker

JavaScript
Sends messages to trigger power
var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://ec2-35-161-110-220.us-west-2.compute.amazonaws.com')
var fs = require('fs'); 
var parse = require('csv-parse');
var moment = require('moment');
var sleep = require('sleep');
var utilPower = 0;
var mapUtil = {"Lights":5,"Heater":15,"Ac":20,"Stove":10}
var csvData;

client.on('connect',function(){
    console.log("Service online");
    fs.createReadStream("Temperature.csv")
    .pipe(parse({delimiter: ':'}))
    .on('data', function(csvrow) {
        csvData = csvData+'\n'+csvrow;
    })
    .on('end',function() {
        client.publish('/Main110_Ac','on');
        client.publish('/stats','Ac on');
        client.publish('/stats','Light on');
        sleep.sleep(5);
        utilPower = utilPower+mapUtil["Ac"];
        client.publish('/Main110_Lights','on');
        utilPower = utilPower+mapUtil["Lights"];
        console.log("Current power utilization : " + utilPower);

        var last = "",lines, i,dbDate,resultDate;
        var dateFormat = 'YYYY-MM-DD HH:mm:ss',minutes = 30,df='HHmm';
        dbDate = '2016-06-11 06:00:00';

        lines = (last+csvData).split("\n");
        for(i = 2; i < 27; i++) {
            if(i>lines.length-1)
            {
                client.publish('/system_time',moment(dbDate).format(df));
                console.log("Logged at : "+moment(dbDate).format(df));
                dbDate = moment(dbDate).add(minutes,'minutes').format(dateFormat);
            }else{
                var str = lines[i].split(",");
                client.publish('/system_time',str[0]);
                client.publish('/system_curtemp',str[1]);
                
                if(parseInt(str[2])-utilPower<=10){
                    console.log("Nothing scheduled, Currently utilizing : "+utilPower);
                }

                if(str[4]!="stats"){
                    client.publish('/Main110_'+str[4],str[5]);
                    client.publish('/stats',str[4]+' '+str[5]);
                    if(str[5]=="on" || str[5]=="1"){
                        utilPower += mapUtil[str[4]];
                        console.log(mapUtil[str[4]]);
                    }
                    else if(str[5]=="off" || str[5]=="0"){
                        utilPower -= mapUtil[str[4]];
                        console.log(mapUtil[str[4]]);
                    }
                    else if(str[5]=="0.5"){
                        utilPower += (mapUtil[str[4]])/2;
                    }
                    console.log("Scheduled event "+str[4]+" switched "+str[5]+" current util : "+utilPower);
                }
                console.log("Logged at : "+str[0]);
                dbDate = moment(dbDate).add(minutes,'minutes').format(dateFormat);
            }
            
            sleep.sleep(5);

            client.publish('/Main110_Lights','0');
            client.publish('/stats','Lights off');
            client.publish('/Main110_Heater','off');
            client.publish('/stats','Heater off');
            client.publish('/Main110_Ac','off');
            client.publish('/stats','Ac off');
            client.publish('/Main110_Stove','off');
            client.publish('/stats','Stove off');
        } 
        process.exit();
});


});

Credits

Al Margolis

Al Margolis

1 project • 5 followers
I am excited about programming and electronics and have lots of experience in both.
Anoja Rajalakshmi

Anoja Rajalakshmi

1 project • 1 follower
Firmware Engineer seeking a serious opportunity to gain vital industry experience in a growing company
Ashok

Ashok

1 project • 0 followers
mhellar

mhellar

2 projects • 7 followers
Mark Hellar is a leading technology consultant for cultural institutions throughout the San Francisco Bay Area and beyond and owner of Hellar Studios LLC.

Comments