Skip to content
This repository was archived by the owner on Nov 21, 2024. It is now read-only.

Commit 04970fb

Browse files
authored
v1.0 Merge to master
Dev > Master v1
2 parents c2a4914 + 98f3ab7 commit 04970fb

File tree

16 files changed

+3229
-2
lines changed

16 files changed

+3229
-2
lines changed

.gitignore

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
2+
# Created by https://www.gitignore.io/api/node,visualstudiocode
3+
# Edit at https://www.gitignore.io/?templates=node,visualstudiocode
4+
5+
### Node ###
6+
# Logs
7+
logs
8+
*.log
9+
npm-debug.log*
10+
yarn-debug.log*
11+
yarn-error.log*
12+
13+
# Runtime data
14+
pids
15+
*.pid
16+
*.seed
17+
*.pid.lock
18+
19+
# Directory for instrumented libs generated by jscoverage/JSCover
20+
lib-cov
21+
22+
# Coverage directory used by tools like istanbul
23+
coverage
24+
25+
# nyc test coverage
26+
.nyc_output
27+
28+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29+
.grunt
30+
31+
# Bower dependency directory (https://bower.io/)
32+
bower_components
33+
34+
# node-waf configuration
35+
.lock-wscript
36+
37+
# Compiled binary addons (https://nodejs.org/api/addons.html)
38+
build/Release
39+
40+
# Dependency directories
41+
node_modules/
42+
jspm_packages/
43+
44+
# TypeScript v1 declaration files
45+
typings/
46+
47+
# Optional npm cache directory
48+
.npm
49+
50+
# Optional eslint cache
51+
.eslintcache
52+
53+
# Optional REPL history
54+
.node_repl_history
55+
56+
# Output of 'npm pack'
57+
*.tgz
58+
59+
# Yarn Integrity file
60+
.yarn-integrity
61+
62+
# dotenv environment variables file
63+
.env
64+
65+
# parcel-bundler cache (https://parceljs.org/)
66+
.cache
67+
68+
# next.js build output
69+
.next
70+
71+
# nuxt.js build output
72+
.nuxt
73+
74+
# vuepress build output
75+
.vuepress/dist
76+
77+
# Serverless directories
78+
.serverless/
79+
80+
# FuseBox cache
81+
.fusebox/
82+
83+
#DynamoDB Local files
84+
.dynamodb/
85+
86+
### VisualStudioCode ###
87+
.vscode/*
88+
!.vscode/settings.json
89+
!.vscode/tasks.json
90+
!.vscode/launch.json
91+
!.vscode/extensions.json
92+
93+
### VisualStudioCode Patch ###
94+
# Ignore all local history of files
95+
.history
96+
97+
# End of https://www.gitignore.io/api/node,visualstudiocode
98+
99+
# Plug state for Home Assistant
100+
states/

README.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,35 @@
1-
# hwl-api
2-
Home Wizard Lite DIY API RESTFUL API
1+
# Home Wizard Lite RESTFUL Proxy API (Node.JS)
2+
HomeWizard Lite Proxy API, built for integrating cheap HomeWizard Lite smartplugs into [Home Assistant](https://www.home-assistant.io/) for example, freeing the user from the dreadful HWL Android or iOS app.
3+
4+
## Installation
5+
6+
$ git clone https://github.com/basvanrooten/hwl-api
7+
$ npm install
8+
$ npm start
9+
$ node index.js
10+
11+
The API depends on environment variables for authentication with HomeWizard API.
12+
13+
| Key | Value |
14+
|--|--|
15+
| HWL_USERNAME | HomeWizard Lite App Username |
16+
| HWL_PASSWORD | HomeWizard Lite App Password |
17+
| LOGLEVEL | [Tracer Logger Level](https://github.com/baryon/tracer#customize-output-format) (default trace) |
18+
19+
## Deploying
20+
The API should be deployed on a local network, because it has no built-in authentication. It is always possible to protect the API with HTTP Basic Auth and make it accessible over the internet, but take note of the insecurities of HTTP Basic Auth.
21+
22+
The API could also be deployed in a docker container
23+
24+
## Requests
25+
|Method | URL | Description |
26+
| -- | -- | -- |
27+
| GET | /api/test/session | Returns valid session key (Only necessary for testing)* |
28+
| GET | /api/test/communication | Returns status 200 when API can connect to Google Test API to verify internet connectivity |
29+
| -- | -- | -- |
30+
| GET | /api/plug | Returns all registered plugs |
31+
| GET | /api/act/smartplug/:smartPlugID/plug/:plugID | Returns `true` or `false` for is_active state of a plug specified by plugID |
32+
| POST | /api/act/smartplug/:smartPlugID/plug/:plugID | Switches plug when request body contains `"action": "on"` or `"action": "off"`. Returns is_active state.
33+
34+
## Contribution
35+
This project was started by an IT-student as a small 2 day project to improve home-automation by enabling Home Assistant to control HomeWizard Lite plugs. Development will continue when I need more features. Contribution is appreciated.

app.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Node dependencies
2+
const express = require('express');
3+
const cors = require('cors');
4+
const bodyParser = require('body-parser');
5+
const morgan = require("morgan");
6+
const config = require('./config/config');
7+
const logger = require('./config/config').logger
8+
9+
// Import models
10+
const ApiResponse = require('./models/ApiResponse');
11+
12+
// Import routes
13+
const test_routes = require('./routes/test_routes');
14+
const plug_routes = require('./routes/plug_routes');
15+
16+
const app = express();
17+
18+
// Parse the request body to JSON
19+
app.use(bodyParser.json());
20+
21+
// Setup Morgan as Logger
22+
app.use(morgan("dev"));
23+
24+
// Enable CORS-support
25+
app.use(cors());
26+
27+
app.get('/', function(req, res, next) {
28+
res.status(200).send(new ApiResponse("Hello World!", 202));
29+
});
30+
31+
app.use('/api', test_routes);
32+
app.use('/api', plug_routes);
33+
34+
35+
36+
//This endpoint is called when no other one was found, and throws a 404 error
37+
app.use('*', function(req, res, next){
38+
res.status(404).send(new ApiResponse("This endpoint doesnt't exist", 404));
39+
});
40+
41+
module.exports = app;

auth/authentication_manager.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const logger = require('../config/config').logger
2+
const config = require('../config/config');
3+
var sha1 = require('sha1');
4+
const axios = require('axios');
5+
6+
module.exports = {
7+
8+
// Get Session Key from HomeWizard Lite
9+
getSessionKey() {
10+
11+
// Get Username and Password from config file
12+
let username = config.hwlUsername;
13+
let password = sha1(config.hwlPassword);
14+
logger.debug(username);
15+
logger.debug(password);
16+
17+
// Login to HWL using user credentials
18+
return axios({
19+
method: 'get',
20+
url: 'https://cloud.homewizard.com/account/login',
21+
auth: {
22+
username: username,
23+
password: password
24+
}
25+
})
26+
.then(response => {
27+
28+
// Check status
29+
if (response.data.status === "ok") {
30+
31+
// Authentication passed, returning session token
32+
logger.debug(response.data.session);
33+
return response.data.session;
34+
35+
} else if (response.data.status === "failed" && response.data.error === 110) {
36+
37+
// Authentication failed, returning FAILED
38+
logger.error("HWL returned invalid credentials! Check credentials for validity!")
39+
logger.debug(response.data);
40+
return "ERROR";
41+
42+
} else {
43+
44+
// Authentication failed, but with unknown reason
45+
logger.error("HWL returned unknown authentication error. ERROR :", response.data);
46+
return "ERROR";
47+
}
48+
})
49+
.catch(e => {
50+
// Cannot communicate with HWL, returning error
51+
logger.error("Failed to communicate with HWL! ERROR: ", e.message);
52+
return "ERROR";
53+
});
54+
}
55+
56+
}

captain-definition

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"schemaVersion": 2,
3+
"templateId": "node/8.7.0"
4+
}

config/config.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Set debug level for tracer
2+
const loglevel = process.env.LOGLEVEL || 'trace'
3+
4+
module.exports = {
5+
6+
// Web port where the server will listen to
7+
"webPort": process.env.PORT || 3000,
8+
"authKey": process.env.AUTHKEY || "",
9+
10+
// Authentication for Homewizard Lite API
11+
"hwlUsername": process.env.HWL_USERNAME || "",
12+
"hwlPassword": process.env.HWL_PASSWORD || "",
13+
14+
15+
// Tracer for logging purposes
16+
logger: require('tracer')
17+
.console({
18+
format: [
19+
"{{timestamp}} <{{title}}> {{file}}:{{line}} : {{message}}"
20+
],
21+
preprocess: function (data) {
22+
data.title = data.title.toUpperCase();
23+
},
24+
dateformat: "isoUtcDateTime",
25+
level: loglevel
26+
})
27+
28+
}

0 commit comments

Comments
 (0)