Skip to content

Commit

Permalink
Merge pull request #28 from copios-jp/master
Browse files Browse the repository at this point in the history
Add Training Reporting
  • Loading branch information
copios authored Jan 13, 2019
2 parents fc6aa96 + a0a750e commit 8c52ed3
Show file tree
Hide file tree
Showing 44 changed files with 1,114 additions and 226 deletions.
38 changes: 36 additions & 2 deletions app/main/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import path from 'path'
import { app, crashReporter, BrowserWindow, Menu, ipcMain } from 'electron'
import { app, crashReporter, BrowserWindow, Menu, ipcMain, shell } from 'electron'
import log from 'electron-log'
import { autoUpdater } from 'electron-updater'

import tooling from './tooling/'
import menuTemplate from './menu_template'
import PowerSaveBlocker from './services/power_save_blocker/'
import scanner from './services/ant/Scanner'
// import scanner from './services/ant/Scanner'
import scanner from './services/ant/SingleUSBReceiverScanner'

import bridge from './services/bridge/'
import fs from 'fs'
import os from 'os'

// TODO - move this kind of setup out of index.js
autoUpdater.logger = log
Expand Down Expand Up @@ -54,6 +58,7 @@ app.on('ready', async () => {
})

mainWindow.webContents.on('will-navigate', () => {
console.log('will navigate')
scanner.deactivate()
})

Expand All @@ -70,13 +75,42 @@ app.on('ready', async () => {
})

app.on('before-quit', () => {
console.log('before quit')
PowerSaveBlocker.deactivate()
})

ipcMain.on('activate', () => {
scanner.activate()
})

ipcMain.on('print', (event, fileName) => {
const pdfPath = path.join(os.tmpdir(), `${fileName}.pdf`)
const win = BrowserWindow.fromWebContents(event.sender)
win.webContents.printToPDF(
{
pageSize: 'A4',
marginsType: 2,
printBackground: true,
},
(err, data) => {
if (err) {
return console.log(err)
}

fs.writeFile(pdfPath, data, (err) => {
if (err) {
return console.log(err)
}

shell.openExternal('file://' + pdfPath)
event.sender.send('print-complete', pdfPath)
})
},
)
scanner.activate()
})

ipcMain.on('deactivate', () => {
console.log('deactivate')
scanner.deactivate()
})
9 changes: 1 addition & 8 deletions app/main/services/ant/Receiver.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import events from 'events'
import Ant from './'
import Transmitter from './Transmitter'
import { inactiveFilter, MAX_INACTIVE_MS as MAX_MS } from './filters'

export const MAX_INACTIVE_MS = MAX_MS
export const SCAN_INTERVAL = MAX_MS + 1000
export const MAX_CHANNELS = 8
export const MAX_LISTENERS = MAX_CHANNELS * 2 // 8 channels with two reads each

export const channels = []
export const transmitters = []
export const pending = []

for (let i = 0; i < MAX_CHANNELS; i++) {
channels.push(i)
}
Expand All @@ -37,10 +34,6 @@ class Receiver extends events.EventEmitter {
transmitter.activate()
}

clean = () => {
;[...transmitters].filter(inactiveFilter).forEach(this.remove)
}

deactivate = () => {
;[...transmitters].forEach((transmitter) => {
this.remove(transmitter)
Expand Down
11 changes: 11 additions & 0 deletions app/main/services/ant/Scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ export const SCAN_INTERVAL = 5000

export const receivers = []

/*
* This class is left here for future reference as I would prefer to be able
* to run multiple USB receivers in order to allow more than eight active transmitters
*
* https://github.com/copios-jp/red-falcon/issues/21
* I am not 100% sure, but it seems like sing the single usb receiver with changes
* to the receiver which detaches all sensors seems to have resolved it.
*
* Client does not need more than eight transmitters right now so
* I am going to defer working in this until there is funding.
* */
class Scanner extends events.EventEmitter {
activate = () => {
this.emit('scanner-activated', this)
Expand Down
31 changes: 31 additions & 0 deletions app/main/services/ant/SingleUSBReceiverScanner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import events from 'events'

import Ant from './'
import Receiver from './Receiver'

class Scanner extends events.EventEmitter {
activate = () => {
const stick = new Ant.GarminStick2(1)
stick.once('startup', this.onStartup.bind(this, stick))
stick.open()
}

deactivate = () => {
if (this.receiver) {
this.receiver.deactivate()
this.emit('receiver-removed', this.receiver, [])
delete this.receiver
}

this.emit('scanner-deactivated', this)
}

onStartup = (stick) => {
this.emit('scanner-activated', this)
this.receiver = new Receiver(stick)
this.emit('receiver-added', this.receiver, [this.receiver])
this.receiver.activate()
}
}

export default new Scanner()
8 changes: 2 additions & 6 deletions app/main/services/ant/Transmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ class Transmitter extends events.EventEmitter {

deactivate = () => {
this.removeAllListeners()
try {
this.sensor.removeAllListeners('hbData')
this.sensor.detach()
} catch (e) {
console.log('Transmitter#deactivate', e)
}
this.sensor.removeAllListeners()
this.sensor.detach()
}

// TODO - make this a debounce that removes the
Expand Down
32 changes: 0 additions & 32 deletions app/main/services/ant/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Transmitter from './Transmitter'
import Receiver from './Receiver'

import { SCAN_INTERVAL, receivers } from './Scanner'
import { MAX_INACTIVE_MS } from './Receiver'
import { MAX_LISTENERS, transmitters } from './Receiver'

const stick = mockApiMember(
Expand Down Expand Up @@ -409,37 +408,6 @@ describe('ant', () => {
})
})

describe('clean', () => {
const receiver = new Receiver(stick)
const outdated = {
updated: new Date(new Date() - (MAX_INACTIVE_MS + 1)),
deactivate: jest.fn(),
}

beforeAll(() => {
transmitters.push({
updated: new Date(),
deactivate: jest.fn(),
})
transmitters.push(outdated)
jest.spyOn(receiver, 'remove')
receiver.clean()
})

afterAll(() => {
;[...transmitters].forEach(() => {
transmitters.shift()
})
receiver.deactivate()
})
it('remove inactive transmitter', () => {
expect(transmitters.length).toEqual(1)
})
it('calls remove with expired transmitter', () => {
expect(receiver.remove.mock.calls[0][0]).toEqual(outdated)
})
})

describe('deactivate', () => {
let transmitter
let receiver
Expand Down
2 changes: 1 addition & 1 deletion app/renderer/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import ReactDOM from 'react-dom'
import tooling from './tooling/'

// import '../../node_modules/react-vis/dist/style.css';
import { MuiThemeProvider } from '@material-ui/core/styles'
import CssBaseline from '@material-ui/core/CssBaseline'
import SensorsView from './components/SensorsView'
Expand Down
10 changes: 6 additions & 4 deletions app/renderer/components/SensorList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export class SensorList extends Component {
bind.call(this, 'off')
}

editSensor = (sensor) => this.setState((state) => ({ ...state, editing: sensor }))
editSensor = (sensor) => {
if (!sensor.state.isRecording) {
this.setState((state) => ({ ...state, editing: sensor }))
}
}

mainEvents = {
onTransmitter: ['transmitter-added', 'transmitter-removed'],
Expand Down Expand Up @@ -62,9 +66,7 @@ export class SensorList extends Component {
}

stopEditing = (data) => {
this.state.editing.setState((state) => {
return { ...state, ...data }
})
this.state.editing.handleChange(data)

this.setState((state) => {
return { ...state, editing: undefined }
Expand Down
33 changes: 24 additions & 9 deletions app/renderer/components/sensor/body/index.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
import React from 'react'
import { Component } from 'react'

import { withStyles } from '@material-ui/core/styles'
import styles from '../../../styles/'
import { getZone, getPercentageOfMax } from '../../../../services/analytics/'

export const Body = (props) => {
const { classes, sensor } = props
return (
<svg style={{ flexGrow: 1 }} className={classes[`rate_${getZone(sensor)}`]}>
<text x="50%" y="50%" dominantBaseline="central" textAnchor="middle" fill="lightgrey">
{`${getPercentageOfMax(sensor)}%`}
</text>
</svg>
)
export class Body extends Component {
shouldComponentUpdate(nextProps) {
const nextSensor = nextProps.sensor
const { sensor } = this.props

return (
nextSensor.rate !== sensor.rate ||
nextSensor.method !== sensor.method ||
nextSensor.max !== sensor.max
)
}

render() {
const { classes, sensor } = this.props
return (
<svg style={{ flexGrow: 1 }} className={classes[`zone_${getZone(sensor)}`]}>
<text x="50%" y="50%" dominantBaseline="central" textAnchor="middle" fill="lightgrey">
{`${getPercentageOfMax(sensor)}%`}
</text>
</svg>
)
}
}

export default withStyles(styles)(Body)
4 changes: 2 additions & 2 deletions app/renderer/components/sensor/edit/Coefficients.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Coefficients extends Component {
<span
key={index}
style={{ width: `${Math.round(100 * (values.max - values.min))}%` }}
className={classes[`rate_${index}`]}>
className={classes[`zone_{index}`]}>
&nbsp;
</span>
)
Expand All @@ -75,7 +75,7 @@ class Coefficients extends Component {
rangeBand(coef, values, index) {
const { classes } = this.props
return (
<div key={index} className={[classes[`rate_${index}`], classes.zoneData].join(' ')}>
<div key={index} className={[classes[`zone_${index}`], classes.zoneData].join(' ')}>
<span className={classes.zoneRangeLabel}>{values.min}</span>
<Button size="small" onClick={this.step.bind(this, -1, index)}>
<RemoveIcon fontSize="small" />
Expand Down
26 changes: 17 additions & 9 deletions app/renderer/components/sensor/footer/index.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import React from 'react'
import { Component } from 'react'

import { Favorite } from '@material-ui/icons'
import { withStyles } from '@material-ui/core/styles'
import styles from '../../../styles/'
import Rate from './rate'

export const Footer = (props) => {
const { classes, sensor } = props
return (
<div className={classes.cardFooter}>
<Favorite fontSize="small" />
<span className={classes.cardRate}>{sensor.rate}</span>
</div>
)
export class Footer extends Component {
shouldComponentUpdate(nextProps) {
const nextSensor = nextProps.sensor
const { sensor } = this.props
return nextSensor.rate !== sensor.rate || nextSensor.recording
}

render() {
const { classes, sensor } = this.props
return (
<div className={classes.cardFooter}>
<Rate rate={sensor.rate} />
</div>
)
}
}

export default withStyles(styles)(Footer)
24 changes: 24 additions & 0 deletions app/renderer/components/sensor/footer/rate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'
import { Component } from 'react'
import { Favorite } from '@material-ui/icons'

import { withStyles } from '@material-ui/core/styles'
import styles from '../../../styles/'

export class Rate extends Component {
shouldComponentUpdate(nextProps) {
return nextProps.rate !== this.props.rate
}

render() {
const { classes, rate } = this.props
return (
<span className={classes.cardRate}>
<Favorite fontSize="small" />
{rate}
</span>
)
}
}

export default withStyles(styles)(Rate)
26 changes: 26 additions & 0 deletions app/renderer/components/sensor/header/history_button/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react'
import { Component } from 'react'
import { Button } from '@material-ui/core'
import { History } from '@material-ui/icons'

export class HistoryButton extends Component {
onClick = (e) => {
e.stopPropagation()
this.props.handleChange({ showReport: true })
}

render = () => {
const { classes, sensor } = this.props
return (
<Button
className={classes.recordButton}
onClick={this.onClick}
color="inherit"
disabled={!sensor.history.length || sensor.recording}>
<History />
</Button>
)
}
}

export default HistoryButton
Loading

0 comments on commit 8c52ed3

Please sign in to comment.