frontend/smart-hut/src/components/dashboard/devices/Sensor.js

213 lines
5.6 KiB
JavaScript
Raw Normal View History

/**
* Users can add sensors in their rooms.
* Sensors typically measure physical quantities in a room.
* You must support temperature sensors, humidity sensors, light sensors (which measure luminosity1).
* Sensors have an internal state that cannot be changed by the user.
* For this story, make the sensors return a constant value with some small random error.
*/
2020-03-23 20:24:17 +00:00
/*
2020-03-23 18:08:31 +00:00
OPTIONAL STATE
error: 2.4
2020-03-23 18:08:31 +00:00
<text style={errorStyle} x={100} y={100} textAnchor="middle" dy="0.6em" fontWeight="bold">
&#177;{this.state.error}
</text>
errorStyle,
*/
2020-05-12 13:18:33 +00:00
import React, { Component } from 'react';
import { CircularInput, CircularProgress } from 'react-circular-input';
import { Image } from 'semantic-ui-react';
import { connect } from 'react-redux';
2020-03-25 15:04:02 +00:00
import {
2020-05-08 13:37:01 +00:00
container,
sensorText,
style,
valueStyle,
motionSensorInnerCircle,
motionSensorOuterCircle,
nameMotionStyle,
motionSensorIcon,
temperatureSensorColors,
lightSensorColors,
humiditySensorColors,
iconSensorStyle,
2020-05-12 13:18:33 +00:00
} from './SensorStyle';
import { RemoteService } from '../../../remote';
import mapStateToProps from '../../../deviceProps';
2020-04-10 15:25:52 +00:00
class Sensor extends Component {
2020-05-08 13:37:01 +00:00
constructor(props) {
super(props);
this.state = {
value: 0,
motion: false,
};
2020-05-12 13:18:33 +00:00
this.units = '';
2020-05-08 13:37:01 +00:00
this.stateCallback = (e) => {
this.setState(Object.assign(this.state, e));
};
2020-05-08 13:37:01 +00:00
this.colors = temperatureSensorColors;
2020-05-12 13:18:33 +00:00
this.icon = 'temperatureIcon.svg';
this.name = 'Sensor';
2020-05-08 13:37:01 +00:00
}
componentDidUpdate(prevProps) {
if (
2020-05-12 13:18:33 +00:00
this.props.stateOrDevice.kind === 'sensor'
&& this.props.stateOrDevice.value !== prevProps.stateOrDevice.value
2020-05-08 13:37:01 +00:00
) {
this.setState({ value: this.props.stateOrDevice.value });
} else if (
2020-05-12 13:18:33 +00:00
this.props.stateOrDevice.kind === 'motionSensor'
&& this.props.stateOrDevice.detected !== prevProps.stateOrDevice.detected
2020-05-08 13:37:01 +00:00
) {
this.setState({
motion: true,
detected: this.props.stateOrDevice.detected,
});
2020-03-23 18:08:31 +00:00
}
2020-05-08 13:37:01 +00:00
}
componentDidMount() {
2020-05-12 13:18:33 +00:00
if (this.props.stateOrDevice.kind === 'sensor') {
2020-05-08 13:37:01 +00:00
switch (this.props.stateOrDevice.sensor) {
2020-05-12 13:18:33 +00:00
case 'TEMPERATURE':
this.units = 'ºC';
2020-05-08 13:37:01 +00:00
this.colors = temperatureSensorColors;
2020-05-12 13:18:33 +00:00
this.icon = 'temperatureIcon.svg';
this.name = 'Temperature Sensor';
2020-05-08 13:37:01 +00:00
break;
2020-05-12 13:18:33 +00:00
case 'HUMIDITY':
this.units = '%';
2020-05-08 13:37:01 +00:00
this.colors = humiditySensorColors;
2020-05-12 13:18:33 +00:00
this.icon = 'humidityIcon.svg';
this.name = 'Humidity Sensor';
2020-05-08 13:37:01 +00:00
break;
2020-05-12 13:18:33 +00:00
case 'LIGHT':
this.units = 'lm';
2020-05-08 13:37:01 +00:00
this.colors = lightSensorColors;
2020-05-12 13:18:33 +00:00
this.icon = 'lightSensorIcon.svg';
this.name = 'Light Sensor';
2020-05-08 13:37:01 +00:00
break;
default:
2020-05-12 13:18:33 +00:00
this.units = '';
2020-05-08 13:37:01 +00:00
}
this.setState({
value: this.props.stateOrDevice.value,
});
} else {
this.setState({
detected: this.props.stateOrDevice.detected,
motion: true,
});
2020-03-24 19:35:23 +00:00
}
2020-05-08 13:37:01 +00:00
}
2020-05-08 13:37:01 +00:00
getIcon = () => {
if (this.state.detected) {
return this.iconOn;
}
return this.iconOff;
};
temperatureColor = (value) => {
let hue = 100;
const min = 16;
const max = 20;
if (value >= min && value < max) {
hue = 100 - ((value - min) * 100) / (max - min);
} else if (value >= max) {
hue = 0;
}
return `hsl(${hue}, 100%, 50%)`;
};
render() {
2020-05-12 13:18:33 +00:00
const MotionSensor = (props) => (
<div
style={{
2020-05-08 13:37:01 +00:00
...motionSensorOuterCircle,
2020-05-12 13:18:33 +00:00
backgroundColor: this.state.detected ? '#505bda' : '#00bdaa',
2020-05-08 13:37:01 +00:00
}}
2020-05-12 13:18:33 +00:00
>
<div
style={{
2020-05-08 13:37:01 +00:00
...motionSensorInnerCircle,
2020-05-12 13:18:33 +00:00
backgroundColor: this.state.detected ? '#fe346e' : '#00bdaa',
2020-05-08 13:37:01 +00:00
}}
2020-05-12 13:18:33 +00:00
>
<Image style={motionSensorIcon} src="/img/motionSensorIcon.svg" />
<span style={nameMotionStyle}>Motion Sensor</span>
2020-05-08 13:37:01 +00:00
</div>
2020-05-12 13:18:33 +00:00
</div>
2020-05-08 13:37:01 +00:00
);
2020-05-08 13:37:01 +00:00
return (
<div style={container}>
{this.state.motion ? (
<MotionSensor />
) : (
2020-05-12 13:18:33 +00:00
<>
2020-05-08 13:37:01 +00:00
<CircularInput
value={
2020-05-12 13:18:33 +00:00
this.props.stateOrDevice.sensor === 'LIGHT'
2020-05-08 13:37:01 +00:00
? this.state.value / 2000
: this.state.value / 100
}
style={style}
>
<CircularProgress
strokeWidth="2rem"
stroke={
2020-05-12 13:18:33 +00:00
this.props.stateOrDevice.sensor === 'TEMPERATURE'
2020-05-08 13:37:01 +00:00
? this.temperatureColor(this.state.value)
: this.colors.progress
}
fill={this.colors.circle}
/>
<text
style={{
...valueStyle,
fill: this.colors.text,
}}
x={100}
y={110}
textAnchor="middle"
dy="0.3em"
fontWeight="bold"
fill={this.colors.text}
>
2020-05-12 13:18:33 +00:00
{+(`${Math.round(`${this.state.value}e+2`)}e-2`)}
2020-05-08 13:37:01 +00:00
{this.units}
</text>
<text
style={{
...sensorText,
fill: this.colors.text,
}}
x={100}
y={150}
textAnchor="middle"
dy="0.4em"
fontWeight="bold"
>
{this.name}
</text>
</CircularInput>
<Image style={iconSensorStyle} src={`/img/${this.icon}`} />
2020-05-12 13:18:33 +00:00
</>
2020-05-08 13:37:01 +00:00
)}
</div>
);
}
}
2020-04-10 15:25:52 +00:00
const SensorContainer = connect(mapStateToProps, RemoteService)(Sensor);
export default SensorContainer;