Add logging

This commit is contained in:
Michael Woods 2021-06-10 23:14:00 -04:00
parent df45a32113
commit ab0011c08d
4 changed files with 3711 additions and 67 deletions

3645
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,8 @@
"convert-units": "^2.3.4",
"lodash": "^4.17.21",
"onstarjs": "^2.2.1",
"uuid": "^8.3.2"
"uuid": "^8.3.2",
"winston": "^3.3.3"
},
"devDependencies": {
"mocha": "^9.0.0",

View File

@ -1,4 +1,3 @@
const OnStar = require('onstarjs');
const mqtt = require('async-mqtt');
const uuidv4 = require('uuid').v4;
@ -7,6 +6,8 @@ const Vehicle = require('./vehicle');
const {Diagnostic} = require('./diagnostic');
const MQTT = require('./mqtt');
const Commands = require('./commands');
const logger = require('./logger');
const onstarConfig = {
deviceId: process.env.ONSTAR_DEVICEID || uuidv4(),
@ -18,6 +19,7 @@ const onstarConfig = {
refreshInterval: parseInt(process.env.ONSTAR_REFRESH) || (30 * 60 * 1000), // 30 min
allowCommands: _.toLower(_.get(process, 'env.ONSTAR_ALLOW_COMMANDS', 'true')) === 'true'
};
logger.info('OnStar Config', {onstarConfig});
const mqttConfig = {
host: process.env.MQTT_HOST || 'localhost',
@ -27,71 +29,75 @@ const mqttConfig = {
tls: process.env.MQTT_TLS || false,
prefix: process.env.MQTT_PREFIX || 'homeassistant',
};
logger.info('MQTT Config', {mqttConfig});
let loop, commands, vehicles;
const init = () => new Commands(OnStar.create(onstarConfig));
const init = async () => {
commands = new Commands(OnStar.create(onstarConfig));
console.log('Requesting vehicles.');
const getVehicles = async commands => {
logger.info('Requesting vehicles');
const vehiclesRes = await commands.getAccountVehicles();
console.log(_.get(vehiclesRes, 'status'));
vehicles = _.map(
logger.info('Vehicle request status', {status: _.get(vehiclesRes, 'status')});
const vehicles = _.map(
_.get(vehiclesRes, 'response.data.vehicles.vehicle'),
v => new Vehicle(v)
);
console.log('Vehicles returned:');
for (const v of vehicles) {
console.log(v.toString());
}
logger.debug('Vehicle request response', {vehicles: _.map(vehicles, v => v.toString())});
return vehicles;
}
const connectMQTT = async () => {
const mqttHA = new MQTT(vehicles[0], 'homeassistant');
const availTopic = mqttHA.getAvailabilityTopic();
const client = await mqtt.connectAsync(`${mqttConfig.tls
? 'mqtts' : 'mqtt'}://${mqttConfig.host}:${mqttConfig.port}`, {
const connectMQTT = async availabilityTopic => {
const url = `${mqttConfig.tls ? 'mqtts' : 'mqtt'}://${mqttConfig.host}:${mqttConfig.port}`;
const config = {
username: mqttConfig.username,
password: mqttConfig.password,
will: {topic: availTopic, payload: 'false', retain: true}
will: {topic: availabilityTopic, payload: 'false', retain: true}
};
logger.info('Connecting to MQTT', {url, config: _.omit(config, 'password')});
const client = await mqtt.connectAsync(url, config);
logger.info('Connected to MQTT');
return client;
}
const configureMQTT = async (commands, client, mqttHA) => {
if (!onstarConfig.allowCommands)
return;
client.on('message', (topic, message) => {
logger.debug('Subscription message', {topic, message});
const {command, options} = JSON.parse(message);
const commandFn = commands[command].bind(commands);
logger.info('Command sent', {command});
commandFn(options || {})
.then(() => logger.info('Command completed', {command}))
.catch(err=> logger.error('Command error', {command, err}));
});
if (onstarConfig.allowCommands) {
client.on('message', (topic, message) => {
console.log(`Subscription message: ${topic} ${message}`);
const {command, options} = JSON.parse(message);
const commandFn = commands[command].bind(commands);
commandFn(options || {})
.then(() => console.log(`Command completed: ${command}`))
.catch(err=> console.error(`Command error: ${command} ${err}`));
});
const topic = mqttHA.getCommandTopic();
console.log(`Subscribed to: ${topic}`);
await client.subscribe(topic);
}
await client.publish(availTopic, 'true', {retain: true});
return {mqttHA, client};
const topic = mqttHA.getCommandTopic();
logger.info('Subscribed to command topic', {topic});
await client.subscribe(topic);
};
(async () => {
try {
await init();
const commands = init();
const vehicles = await getVehicles(commands);
const {mqttHA, client} = await connectMQTT();
const mqttHA = new MQTT(vehicles[0], 'homeassistant');
const availTopic = mqttHA.getAvailabilityTopic();
const client = await connectMQTT(availTopic);
await configureMQTT(commands, client, mqttHA);
const configurations = new Map();
const run = async () => {
const states = new Map();
const v = vehicles[0];
console.log('Requesting diagnostics:')
const statsRes = await commands.diagnostics({
diagnosticItem: v.getSupported()
});
console.log(_.get(statsRes, 'status'));
logger.info('Requesting diagnostics');
const statsRes = await commands.diagnostics({diagnosticItem: v.getSupported()});
logger.info('Diagnostic request status', {status: _.get(statsRes, 'status')});
const stats = _.map(
_.get(statsRes, 'response.data.commandResponse.body.diagnosticResponse'),
d => new Diagnostic(d)
);
logger.debug('Diagnostic request response', {stats: _.map(stats, s => s.toString())});
for (const s of stats) {
if (!s.hasElements()) {
@ -108,30 +114,36 @@ const connectMQTT = async () => {
const payload = mqttHA.getStatePayload(s);
states.set(topic, payload);
}
// publish configs
const publishes = [];
// publish sensor configs
for (let [topic, config] of configurations) {
// configure once
if (!config.configured) {
config.configured = true;
const {payload} = config;
console.log(`${topic} ${JSON.stringify(payload)}`);
await client.publish(topic, JSON.stringify(payload), {retain: true});
logger.info('Publishing message', {topic, payload});
publishes.push(
client.publish(topic, JSON.stringify(payload), {retain: true})
);
}
}
// update states
// update sensor states
for (let [topic, state] of states) {
console.log(`${topic} ${JSON.stringify(state)}`);
await client.publish(topic, JSON.stringify(state), {retain: true});
logger.info('Publishing message', {topic, state});
publishes.push(
client.publish(topic, JSON.stringify(state), {retain: true})
);
}
await Promise.all(publishes);
};
const main = () => run()
.then(() => console.log('Done, sleeping.'))
.catch(e => console.error(e))
const main = async () => run()
.then(() => logger.info('Updates complete, sleeping.'))
.catch(e => logger.error('Error', {error: e}))
await main();
loop = setInterval(main, onstarConfig.refreshInterval);
setInterval(main, onstarConfig.refreshInterval);
} catch (e) {
console.error(e);
logger.error('Main function error.', {error: e});
}
})();
})();

12
src/logger.js Normal file
View File

@ -0,0 +1,12 @@
const winston = require('winston');
const _ = require('lodash');
const logger = winston.createLogger({
level: _.get(process, 'env.LOG_LEVEL', 'info'),
format: winston.format.simple(),
// format: winston.format.json(),
transports: [new winston.transports.Console({stderrLevels: ['error']})]
})
module.exports = logger;