diff --git a/src/graphql/graphqlModules/Miner/MinerOnline.js b/src/graphql/graphqlModules/Miner/MinerOnline.js new file mode 100644 index 0000000..d6309bf --- /dev/null +++ b/src/graphql/graphqlModules/Miner/MinerOnline.js @@ -0,0 +1,27 @@ +module.exports.typeDefs = ` + type MinerActions { + online: MinerOnlineOutput! + } + + type MinerOnlineOutput { + result: MinerOnlineResult + error: Error + } + + type MinerOnlineResult { + online: MinerOnline! + } + + type MinerOnline { + timestamp: String! + status: Boolean! + } +` + +module.exports.resolvers = { + MinerActions: { + online (root, args, { dispatch }) { + return dispatch('api/miner/online') + } + } +} diff --git a/src/graphql/graphqlModules/Miner/MinerStats.js b/src/graphql/graphqlModules/Miner/MinerStats.js index 66cec6e..ab57924 100644 --- a/src/graphql/graphqlModules/Miner/MinerStats.js +++ b/src/graphql/graphqlModules/Miner/MinerStats.js @@ -25,12 +25,12 @@ module.exports.typeDefs = ` type MinerStatsDevs { status: MinerStatsStatus - data: MinerStatsDevsData + data: [MinerStatsDevsData] } type MinerStatsPools { status: MinerStatsStatus - data: MinerStatsPoolsData + data: [MinerStatsPoolsData] } type MinerStatsStatus { diff --git a/src/store/api/miner/minerOnline.js b/src/store/api/miner/minerOnline.js new file mode 100644 index 0000000..b86eee4 --- /dev/null +++ b/src/store/api/miner/minerOnline.js @@ -0,0 +1,26 @@ +const { exec } = require('child_process') + +module.exports = ({ define }) => { + define('online', async (payload, { knex, errors, utils }) => { + const online = await isMinerOnline() + online.timestamp = new Date().toISOString() + return { online } + }, { + auth: true + }) +} + +function isMinerOnline () { + return new Promise((resolve, reject) => { + exec('systemctl is-active bfgminer >/dev/null 2>&1 && echo true || echo false', {}, (err, stdout) => { + if (err) { + reject(err) + } else { + const current = stdout.toString().replace(/(\r\n|\n|\r)/gm, ''); + const status = (current == 'true'); + + resolve({ status: status }); + } + }) + }) +} diff --git a/src/store/api/miner/minerStats.js b/src/store/api/miner/minerStats.js index 2e8c119..1083e0d 100644 --- a/src/store/api/miner/minerStats.js +++ b/src/store/api/miner/minerStats.js @@ -5,14 +5,14 @@ const Client =require('../../../app/minerClient'); module.exports = ({ define }) => { define('stats', async (payload, { knex, errors, utils }) => { - const stats = await getMinerStats() + const stats = await getMinerStats(errors) return { stats } }, { auth: true }) } -function getMinerStats () { +function getMinerStats (errors) { const client = new Client(); return new Promise((resolve, reject) => { @@ -21,6 +21,7 @@ function getMinerStats () { client.socket.on('data', (data) => { let received = data.toString('utf8').trim(); try { + // JSON from bfgminer is dirty, clean it received = received .replace(/\-nan/g, '0') .replace(/[^\x00-\x7F]/g, '') @@ -34,6 +35,10 @@ function getMinerStats () { const devs = (received.devs && received.devs[0]) ? received.devs[0] : null; const pools = (received.pools && received.pools[0]) ? received.pools[0] : null; + // Always converts pools in an array + let poolsArray = pools.POOLS || []; + if (poolsArray && !Array.isArray(poolsArray)) poolsArray = [poolsArray]; + let results = { summary: { status: (summary.STATUS && summary.STATUS[0]) ? summary.STATUS[0] : null, @@ -41,26 +46,32 @@ function getMinerStats () { }, devs: { status: (devs.STATUS && devs.STATUS[0]) ? devs.STATUS[0] : null, - data: (devs.DEVS && devs.DEVS[0]) ? devs.DEVS[0] : null + data: devs.DEVS || null }, pools: { status: (pools.STATUS && pools.STATUS[0]) ? pools.STATUS[0] : null, - data: (pools.POOLS && pools.POOLS[0]) ? pools.POOLS[0] : null + data: poolsArray } } + // Normalize object keys to fit GraphQL and be code-friendly results = normalize(results, 'camel'); resolve(results) } catch (err) { - reject(err); + reject(new errors.InternalError(err.toString())); } client.socket.destroy(); }); client.socket.on('error', (err) => { - reject(err); + reject( + new errors.InternalError(err.toString()).addReason({ + path: 'stats', + message: err.code + }) + ); }); });