node-red-contrib-niu-cloud
Version:
A Node-RED library for connect to NIU Cloud for your electric scooter
165 lines (142 loc) • 4.93 kB
JavaScript
/* eslint-disable no-shadow */
/* eslint-disable no-unused-vars */
/* eslint-disable no-console */
const niuCloudConnector = require('niu-cloud-connector');
// eslint-disable-next-line func-names
module.exports = function (RED) {
function NiuCloudClientNode(conf) {
const node = this;
RED.nodes.createNode(this, conf);
this.niu_user = (this.credentials) ? this.credentials.niu_user : 'n/a';
this.niu_password = (this.credentials) ? this.credentials.niu_password : 'n/a';
this.vehicleSN = (this.credentials) ? this.credentials.vehicleSN : 'n/a';
this.token = false;
this.dbg_low = conf.dbg_low;
this.dbg_cloud = conf.dbg_cloud;
this.name = conf.name;
this.cloud = new niuCloudConnector.Client();
if (this.dbg_cloud) {
this.cloud.enableDebugMode(true);
}
this.REFRESH_TOKEN_TIMEOUT_SECONDS = 3;
this.dbglog = (msg, data) => {
if (node.dbg_low) {
node.log(msg);
if (data !== undefined) {
if (typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean') {
node.log(data);
} else {
node.log(JSON.stringify(data, null, ' '));
}
}
}
};
this.getToken = () => node.token;
this.statusCloudConnected = () => {
node.emit('cloud-connected');
node.dbglog('Cloud Connected');
};
this.statusCloudDisconnected = () => {
node.emit('cloud-disconnected');
node.dbglog('Cloud Disconnected');
};
this.tokenError = () => {
node.statusCloudDisconnected();
node.log('Try to refresh token...');
setTimeout(() => {
node.refreshToken();
}, node.REFRESH_TOKEN_TIMEOUT_SECONDS * 1000); // try to reconnect
};
this.refreshToken = () => {
const loginData = {
account: node.niu_user,
password: node.niu_password,
};
node.dbglog('Refresh Token...');
node.cloud.createSessionToken(
loginData,
).then((result) => {
const logToken = `***********${result.result.substring(result.result.length - 8)}`; // hide full token from logs
node.dbglog(` ...Token created: ${logToken}`);
node.token = result.result;
node.statusCloudConnected();
}).catch((err) => {
node.log(' ...Login error - Bad credential');
node.token = false;
node.statusCloudDisconnected();
});
};
this.refreshToken();
}
RED.nodes.registerType('niu-cloud-client', NiuCloudClientNode, {
credentials: {
niu_user: { type: 'text' },
niu_password: { type: 'password' },
vehicleSN: { type: 'text' },
},
});
// refresh token
RED.httpAdmin.post('/niu/token/:id', RED.auth.needsPermission('niu-cloud.write'), (req, res) => {
const node = RED.nodes.getNode(req.params.id);
const data = req.body;
let pwd = data.niu_password;
if (pwd === '__PWRD__' && node.credentials) {
pwd = node.credentials.niu_password;
}
const loginData = {
account: data.niu_user,
password: pwd,
};
const cloud = new niuCloudConnector.Client();
cloud.createSessionToken(
loginData,
).then((result) => {
const newToken = result.result;
const logToken = `***********${newToken.substring(newToken.length - 8)}`; // hide full token from logs
console.log(`Session token created: ${logToken}`);
// retrive vehicles
cloud.setSessionToken({
token: newToken,
}).then((result) => result.client.getVehicles())
.then((result) => {
const vehicles = result.result;
const list = [];
vehicles.forEach((vehicle) => list.push({ sn: vehicle.sn, type: vehicle.type, name: vehicle.name }));
res.json(list).end();
}).catch((err) => {
console.log('err', err);
const resdata = {
error: 'No vehicles',
};
res.status(404).json(resdata);
});
}).catch((err) => {
console.log('Login error - Bad credential');
const resdata = {
error: 'Bad credential',
};
res.status(401).json(resdata);
});
});
// refresh vehicles list
RED.httpAdmin.get('/niu/vehicles/:id', RED.auth.needsPermission('niu-cloud.write'), (req, res) => {
const node = RED.nodes.getNode(req.params.id);
if (node === undefined || node === null) {
res.status(400).json({}).end();
return;
}
node.cloud.setSessionToken({
token: node.token,
}).then((result) => result.client.getVehicles()).then((result) => {
const vehicles = result.result;
const list = [];
vehicles.forEach((vehicle) => list.push({ sn: vehicle.sn, type: vehicle.type, name: vehicle.name }));
res.json(list).end();
}).catch((err) => {
const resdata = {
error: 'No vehicles',
};
res.status(404).json(resdata);
});
});
};