Skip to content

Commit

Permalink
Merge pull request #1 from FMeneguzzo/master
Browse files Browse the repository at this point in the history
Master
  • Loading branch information
MFava91 committed Apr 23, 2017
2 parents ad8f3c6 + 5758854 commit f634ed2
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 68 deletions.
40 changes: 40 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"extends": "eslint:recommended",
"env": {
"es6": true,
"node": true
},
"rules": {
"arrow-body-style": "off",
"no-console": "off",
"no-continue": "off",
"brace-style": "error",
"curly": "error",
"default-case": "error",
"eqeqeq": "error",
"guard-for-in": "error",
"indent": [
"error",
2, {
"VariableDeclarator": 2,
"SwitchCase": 1
}
],
"linebreak-style": ["error", "unix"],
"no-var": "error",
"no-eval": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-undefined": "error",
"no-unused-expressions": "error",
"no-useless-call": "error",
"no-useless-concat": "error",
"no-useless-escape": "error",
"no-void": "error",
"no-with": "error",
"one-var": ["error", "never"],
"quotes": ["error", "single"],
"radix": "error",
"semi": ["error", "always"]
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Dependency directory
node_modules
coverage

# Other
.DS_Store
Expand Down
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{
"name": "smartoilet",
"version": "0.0.1",
"version": "0.0.2",
"description": "smart toilet",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
"start": "node server.js",
"test-server": "mocha './tests/server/**/*.js' --recursive --check-leaks --reporter min --timeout 60000",
"coverage-server": "istanbul cover ./node_modules/mocha/bin/_mocha -- 'tests/server/**/*.js' --timeout 60000"
},
"author": "",
"license": "ISC",
Expand All @@ -15,5 +17,11 @@
"morgan": "^1.8.1",
"onoff": "^1.1.2"
},
"devDependencies": {}
"devDependencies": {
"chai": "^3.5.0",
"eslint": "^3.19.0",
"istanbul": "^0.4.5",
"mocha": "^3.2.0",
"proxyquire": "^1.7.11"
}
}
22 changes: 14 additions & 8 deletions public/controllers/MainCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@

//---- variable ---------
mainCtrl.status = {
lightSensor: 1,
timeLightSensorIsOn: 0,
motionSensor: 0,
timeMotionSensorIsOff: 0,
lightSensor: {
value: 0,
timeOn: 0,
timeOff: 0
},
motionSensor: {
value: 0,
timeOn: 0,
timeOff: 0
}
};

mainCtrl.lightTimer = {
Expand Down Expand Up @@ -59,11 +65,11 @@
MainService.getStatus().then(function (status) {
mainCtrl.status = status;

if(mainCtrl.status.lightSensor == 0) {
if(mainCtrl.status.lightSensor.value === 0) {
$('#light_icon').css('fill', '#FFD166');
if(!mainCtrl.lightTimer.timerStarted) {
mainCtrl.lightTimer.timerStarted = true;
mainCtrl.lightTimer.time = angular.copy(status.timeLightSensorIsOn);
mainCtrl.lightTimer.time = angular.copy(status.lightSensor.timeOn);
}

} else {
Expand All @@ -72,15 +78,15 @@
mainCtrl.lightTimer.time = 0;
}

if(mainCtrl.status.motionSensor == 1) {
if(mainCtrl.status.motionSensor.value === 1) {
$('#motion_icon').css('fill', '#EF476F');
mainCtrl.motionTimer.timerStarted = false;
mainCtrl.motionTimer.time = 0;
} else {
$('#motion_icon').css('fill', '#363732');
if(!mainCtrl.motionTimer.timerStarted) {
mainCtrl.motionTimer.timerStarted = true;
mainCtrl.motionTimer.time = angular.copy(status.timeMotionSensorIsOff);
mainCtrl.motionTimer.time = angular.copy(status.motionSensor.timeOff);
}
}
});
Expand Down
12 changes: 6 additions & 6 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<div class="col-xs-12 no-padding" ng-class="mainCtrl.lightTimer.minutes >= 20 ? 'margin-bottom-10' : 'margin-bottom-40'">
<p>Light sensor</p>
<img class="icon sensor-icon" src="img/light.svg">
<p style="font-size: 60%" ng-bind="mainCtrl.status.lightSensor == 0 ? 'ON' : 'OFF'"></p>
<p style="font-size: 60%" ng-bind="mainCtrl.status.lightSensor.value == 0 ? 'ON' : 'OFF'"></p>
<p style="font-size: 90%; font-weight: bold" ng-if="mainCtrl.lightTimer.timerStarted && mainCtrl.lightTimer.minutes >= 20">
{{ mainCtrl.lightTimer.hours > 0 ? mainCtrl.lightTimer.hours + ':' : '' }}
{{ mainCtrl.lightTimer.minutes < 10 ? '0' + mainCtrl.lightTimer.minutes : mainCtrl.lightTimer.minutes }} :
Expand All @@ -61,25 +61,25 @@
<div class="col-xs-12">
<p>Motion sensor</p>
<img class="icon sensor-icon" src="img/motion.svg">
<p style="font-size: 60%" ng-bind="mainCtrl.status.motionSensor == 1 ? 'ON' : 'OFF'"></p>
<p style="font-size: 60%" ng-bind="mainCtrl.status.motionSensor.value == 1 ? 'ON' : 'OFF'"></p>
<p style="font-size: 90%; font-weight: bold" ng-if="mainCtrl.motionTimer.timerStarted && mainCtrl.lightTimer.minutes >= 20 && mainCtrl.motionTimer.minutes >= 2">
{{ mainCtrl.motionTimer.hours > 0 ? mainCtrl.motionTimer.hours + ':' : '' }}
{{ mainCtrl.motionTimer.minutes < 10 ? '0' + mainCtrl.motionTimer.minutes : mainCtrl.motionTimer.minutes }} :
{{ mainCtrl.motionTimer.seconds < 10 ? '0' + mainCtrl.motionTimer.seconds : mainCtrl.motionTimer.seconds }}</p>
</div>
</div>
<div class="col-xs-6 col-sm-3 text-center">
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor == 1">
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor.value == 1">
<img class="icon status-icon" ng-src="img/toilet.svg">
</div>
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor == 0">
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor.value == 0">
<img class="icon status-icon" ng-src="img/disturb.svg">
</div>
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor == 1 && mainCtrl.lightTimer.timerStarted && mainCtrl.lightTimer.minutes >= 10
<div class="col-xs-12 no-padding" ng-if="mainCtrl.status.lightSensor.value == 1 && mainCtrl.lightTimer.timerStarted && mainCtrl.lightTimer.minutes >= 10
&& mainCtrl.motionTimer.timerStarted && mainCtrl.motionTimer.minutes >= 2">
<img class="icon status-icon" ng-src="img/question.svg">
</div>
<p style="font-size: 74%" ng-if="mainCtrl.lightTimer.minutes < 10 || mainCtrl.motionTimer.minutes < 5" ng-bind="mainCtrl.status.lightSensor == 1 ? 'AVAILABLE' : 'OCCUPIED'"></p>
<p style="font-size: 74%" ng-if="mainCtrl.lightTimer.minutes < 10 || mainCtrl.motionTimer.minutes < 5" ng-bind="mainCtrl.status.lightSensor.value == 1 ? 'AVAILABLE' : 'OCCUPIED'"></p>
<p style="font-size: 74%" ng-if="mainCtrl.lightTimer.minutes >= 10 && mainCtrl.motionTimer.minutes >= 5">MAYBE AVAILABLE?!</p>
</div>
</div>
Expand Down
59 changes: 51 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
![SmarTo home page](doc/SmarTo_home.jpg)

We installed it in a bathroom with no windows, so the light sensor makes the bulk of the work. The motion sensor comes in handy when someone forgets to turn off the light.
In fact, if after 10 minutes the light still on and there are no movement inside, SmarTo notifies than maybe the toilet is available.
In fact, if the light has been on but there have been no movements within the past 10 minutes, SmarTo will notify that the toilet may be available.

![SmarTo hardware](doc/SmarTo.jpg)

## What it is made of

### Hardaware
### Hardware

- Single-board computer (es: Raspberry Pi/OrangePi)
- Battery pack
- Battery pack (optional)
- Photosensitive resistance sensor module
- HC-SR501 Pir Motion Detector - [Doc](https://www.mpja.com/download/31227sc.pdf)
- Jumper Wires x 6
Expand All @@ -33,9 +33,9 @@ Example on Raspberry Model B+:

<img src="doc/SmarTo_diagram.png" width="524px" height="800px">

After that you need to set the select GPIO on _server.js_.
After that you need to set the selected GPIO in the _server.js_ file.

Example with _Raspberry Model B+_ and previews connection:
Example with _Raspberry Model B+_ and connections preview:

```javascript
// Set GPIO number
Expand Down Expand Up @@ -66,10 +66,10 @@ Make sure you have installed all of the following prerequisites on your machine.
To install SmarTo's dependencies you are going to use npm. In the application root folder run this in the command-line:

```bash
$ npm install
$ npm install --production
```

## Running SmarTo
## Running SmarTo

After the install process is over, you'll be able to run *SmarTo*:

Expand Down Expand Up @@ -101,10 +101,53 @@ Now *SmarTo* is running _forever_ on server port 80.

| Board | OS | Tested |
| --- | --- | --- |
| Raspberry Pi 1 Model B+ | Raspian | NO |
| Raspberry Pi 1 Model B+ | Raspbian | NO |
| Raspberry Pi 3 Model B | Raspbian | YES |
| OrangePi Lite | Armbian | YES |


## Local development and tests

To include development dependencies in the installation procedure, run this command from the application root folder:

```bash
$ npm install
```

After the installation process is over, you'll be able to run *SmarTo* locally by adding the _NODE_ENV_ environment variable:
(Note: example below only works for UNIX systems)

```bash
$ NODE_ENV=development node server.js
```

*SmarTo* will be running locally on the port specified in the _server.js_ file.

While running locally, the sensor value reads will be mocked since the GPIO library is compiled only for ARM architectures. You can change the value returned from the read function of the mocked sensors by editing the value in these lines of code in the _server/sensors.js_ file:

```javascript
const Gpio = process.env.NODE_ENV === 'development' ?
function Gpio() {
this.read = (cb) => cb(null, 0); // <--- your value here (0 or 1)
this.unexport = () => {};
} :
require('onoff').Gpio;
```

To run tests for the server part of the application, run this command:

```bash
$ npm run test-server
```

To run tests and generate the coverage for the server part application, run this command:

```bash
$ npm run coverage-server
```

The coverage files will be generated in the _coverage/_ folder, in the root folder of the project.

## Something you have to know

- This is a little project built and develop in a week, in my free time after work. Many features are missing and the sensors can still be changed.
Expand Down
52 changes: 9 additions & 43 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,17 @@
var express = require('express');
var app = express();
var morgan = require('morgan');
var Gpio = require('onoff').Gpio;
const express = require('express');
const morgan = require('morgan');
const sensors = require('./server/sensors');

// Set GPIO number
var motionSensor = new Gpio(6, 'in', 'both');
var lightSensor = new Gpio(1,'in', 'both');
sensors.init();

var sensor = {
lightSensor: 0,
timeLightSensorIsOn: 0,
motionSensor: 0,
timeMotionSensorIsOff: 0
}
const app = express();


function getLightSensorStatus() {
lightSensor.read(function (err, value) {
sensor['lightSensor'] = value;
if(value == 0) {
sensor['timeLightSensorIsOn'] += 3;
} else {
sensor['timeLightSensorIsOn'] = 0;
}
motionSensor.read(function (err, value) {
sensor['motionSensor'] = value;
if(value == 0) {
sensor['timeMotionSensorIsOff'] += 3;
} else {
sensor['timeMotionSensorIsOff'] = 0;
}
});
});
}

setInterval(getLightSensorStatus, 3000);

app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/public'));
app.use(morgan('dev'));

app.get('/status', function (req, res) {
res.send(sensor);
})

process.on('SIGINT', function () {
motionSensor.unexport();
app.get('/status', (req, res) => {
res.status(200).json(sensors.getSensorsStatus());
});

app.listen(80);
console.log("App listening on port 80");
console.log('App listening on port 80');
53 changes: 53 additions & 0 deletions server/sensors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const Gpio = process.env.NODE_ENV === 'development' ?
function Gpio() {
this.read = (cb) => cb(null, 0);
this.unexport = () => {};
} :
require('onoff').Gpio;

// Set GPIO number
const motionSensor = new Gpio(6, 'in', 'both');
const lightSensor = new Gpio(1, 'in', 'both');

process.on('SIGINT', () => {
lightSensor.unexport();
motionSensor.unexport();
process.exit();
});

const defaultStatus = {
value: 0,
timeOn: 0,
timeOff: 0
};

const status = {
lightSensor: Object.assign({}, defaultStatus),
motionSensor: Object.assign({}, defaultStatus)
};

const init = () => {
return setInterval(() => {
updateSensorStatus(lightSensor, status.lightSensor, 0);
updateSensorStatus(motionSensor, status.motionSensor, 1);
}, 3000);
};

const updateSensorStatus = (sensor, statusObj, onStatus) => {
sensor.read((err, value) => {
const eq = value === onStatus;
statusObj.value = value;
statusObj.timeOn = 0 + ((+ eq) * (statusObj.timeOn + 3));
statusObj.timeOff = 0 + ((+!eq) * (statusObj.timeOff + 3));
});
};

const getSensorsStatus = () => {
return Object.assign({}, status);
};

module.exports = {
init: init,
updateSensorStatus: updateSensorStatus,
getSensorsStatus: getSensorsStatus
};
Loading

0 comments on commit f634ed2

Please sign in to comment.