Home Automation Project [SmartSpinach]

Home Automation

Because IoT is crap.


This is a rewrite of a former project I’ve implimented into my home. My goal is to integrate current standards for security and communication for the web server. This will be an open source project that anybody is welcome to use or contribute to.

Techniques and Technologies

  • PHP/JavaScript/C++ Languages
  • Object Oriented Programming
  • OWASP Guided Project
  • Modular Library

References

System Overview
System topology seperates the client from the controller. The web server handles authentication, metrics, commands and requests to controllers. The controller will have basic authentication and should reside within a protected and firewalled network.
[ Client <-> Webserver <-> Arduino <-> Sensors ]


The Software
This project will be separated into three parts. Follow the corresponding posts below as they will be developed in tandem.

  1. HVAC Controller [Click] - Basic looping program to handle heating and cooling. Simple http communication.
  2. Web UI Control [Click] - Input from user or schedule will be sent to the controller to adjust behavior.
  3. Web Telemetry [Click] - Monitor and record statistics from controller inputs and outputs.

Format
Tabbed, long hand, lower case first letter on variables, upper case first letter on functions and classes. Comment, yes please.

Void function FunkyChicken()
{
	If(condition)
	{
		//do something
	}
}
2 Likes

HVAC Controller

Update: Nov 3 2016
Added files to github

Web Telemetry

Update: January 19, 2038 03:14:07

To begin this project I will need to define the library structure, and integration of systems such as PHP and MySQL.

Currently the application is as such...

Entry page (Index.php)
Functions (func_user.php)
Mysql Data (data_user.php)
Html Data (html_index.php)


Index.php

Client entry point
Includes external sources such as methods for user authentication and html parser.

include("func_user.php");
include("func_page.php");
include("func_mobile.php");
include("html_index.php");

The entry page takes in data from page forms and pushes the data to the function page.

if(isset($_POST["loginsubmit"]))
{
	$Form = new Form($_POST);
	$User->login($Form->getFields());
	if($User->status() > 1)
	{
		$error = 5;
	}
}
else
{
	$User->logout();
}

$logged_in = $User->status();

Finally the page is buffered, generated and output to the user.

if(!mobile())
{
	// Construct for header
	$Main = new Page($logged_in, "index");

	h_index($news);

	$Main->status();
	// Destruct for footer
}

func_user.php

Application accessible only.
Includes external sources for classes that handle MySql queries.
Methods for accessing, manipulating and storing data regarding the specific module (user in this case) are contained within this file.

// Initialize
include("data_user.php");

class User extends UserDB
{
	private $info = Array();
	
	function __construct()
	{
		parent::__construct();
		$this->info[0] = $this->checkLogin();
	}
	
	private function checkLogin()
	{

data_user.php

Application accessible only.
Inherits a configuration class that defines database authorization.
SQL queries reside here. The methods for accessing and returning the database results are in this file as well.

// Initialize
include_once("data_config.php");

class UserDB extends DB
{

	function __construct()
	{
		parent::__construct();
	}

I felt this structure would alleviate adding new pages and functionality to the system. So far it feels relatively easy to maintain even after I forgotten why or how I did something within the code.

Some changes I will be working on are moving to session like authentication storage. Where a cookie is used to store a "session ID". The session information will be saved in a database containing the user ID, expiration and some references to last login IP and browser fingerprinting.

Lastly the method for SQL queries will change to prepared statements.

http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

Tomorrow Ill upload the old sources to github and begin working on the implementation.

1 Like

Cool project, and nice of you to share. Would like to do something like you are doing one day, Looking forward to seeing your project progress.

Thanks, wish I had more time to devote to it.

Update:
All intitial files are not up on Gitlab.

Trying to use Git for the first time too, unsure if I like using cli, may try a gui.

I will begin implementing the new session and authentication changes next.

Also, added some images to the UI post HERE.
Its running off a usb wall wart and needs to be on a dedicated 5v power supply. The relay board needs to be powered from the supply as well, I think this will prevent the temperature spikes when cooling or heating is called and the relay is energized.

Regarding the Git CLI, I felt the same way at first, but now for everything except super weird merging craziness. It's wonderful once you get good at it, GUIs are bulky and awkward.

looks cool I might try using this later

1 Like

Started implementing the session system.

I imagine the session ID will be generated at login and saved in a cookie on the clients system.
Upon successive visits the user session will be verified for a timeout, and dumped if expired.

If a good session exists then compare known user agents and ip addresses.

If both user agent and ip are unrecognized the user must sign in again. Only one is required to maintain the session.

Three ip addresses and three user agents are saved in a string format. The data will be ran through md5 to shorten and obfuscate the users information.

Added and increased cell sizes for user table. Password_Hash recommends storage up to 255 chars. MD5 are only 32 char long x3 plus delimiters.

password varchar(255),
session varchar(255),
address varchar(128),
agents varchar(128),

I figured a way to measure the threat based on unverified information would be easiest to verify.

if(time() > $sInfo['timeout'])											// $timeout = time() + (30 * 24 * 60 * 60); // session older than 30 days
{
	// unset session
	return 0;
}
else
{
	// reset timeout
	
	$threat = 0;
	$agent = encrypt($_SERVER['HTTP_USER_AGENT'], TRUE);
	if(strpos($sInfo['agents'], $agent) === FALSE)						// User agent not recognized
	{
		// add user agent
		$threat++;
	}
	
	$ipAdr = encrypt($_SERVER['REMOTE_ADDR'], TRUE);
	if(strpos($sInfo['address'], $ipAdr) === FALSE)
	{
		// add ip address
		$threat++;
	}
	
	if($threat > 1)
	{
		return 0;
	}
}

More on Github, Hope to have this functional the next update.

1 Like