Connection frontend-backend for Curtains and Thermostat. Added button to handle off/on of thermostats

This commit is contained in:
Christian Capeáns Pérez 2020-04-23 16:55:44 +02:00
parent e0dd8f1273
commit 3ca1f519b6
8 changed files with 545 additions and 156 deletions

View file

@ -1,11 +1,11 @@
import React, {Component} from "react"; import React, { Component } from "react";
import "./Curtains.css";
import { RemoteService } from "../../../remote"; import { RemoteService } from "../../../remote";
import { connect } from "react-redux"; import { connect } from "react-redux";
import {Slider} from "@material-ui/core"; import { Slider } from "@material-ui/core";
class Curtain extends Component { class Curtain extends Component {
constructor (props){ constructor(props) {
super(props); super(props);
this.state = { intensity: this.props.device.intensity, timeout: null }; this.state = { intensity: this.props.device.intensity, timeout: null };
@ -54,47 +54,79 @@ class Curtain extends Component {
.catch((err) => console.error("curtains update error", err)); .catch((err) => console.error("curtains update error", err));
}; };
helper=()=>{ helper = () => {
if(this.props.device.intensity>=90){ if (this.props.device.intensity >= 90) {
this.setIntensity(1); this.setIntensity(1);
this.saveIntensity(); this.saveIntensity();
}else { } else {
this.setIntensity(this.props.device.intensity / 100 + 0.10); this.setIntensity(this.props.device.intensity / 100 + 0.1);
this.saveIntensity(); this.saveIntensity();
} }
}; };
helper2=()=>{ helper2 = () => {
if(this.props.device.intensity<=10){ if (this.props.device.intensity <= 10) {
this.setIntensity(0); this.setIntensity(0);
this.saveIntensity(); this.saveIntensity();
}else { } else {
this.setIntensity(this.props.device.intensity / 100 - 0.10); this.setIntensity(this.props.device.intensity / 100 - 0.1);
this.saveIntensity(); this.saveIntensity();
} }
}; };
helper3=(a)=>{ helper3 = (a) => {
//console.log(a); //console.log(a);
this.setIntensity(a/100); this.setIntensity(a / 100);
this.saveIntensity(); this.saveIntensity();
}; };
///*this took me way too much more time than it should have*/ ///*this took me way too much more time than it should have*/
render(){
return <div><p>{this.props.device.intensity}</p> handleChange = (a) => {
this.setIntensity(a.target.value / 100);
this.saveIntensity();
};
render() {
return (
<div className="container">
<div
className="open-container"
style={{
height: (9 * this.props.device.intensity) / 100 + "rem",
}}
></div>{" "}
<span className="span-open">
{Math.round(this.props.device.intensity)}%
</span>
<input
onChange={this.handleChange}
value={this.props.device.intensity}
className="slider"
type="range"
min="0"
max="100"
/>
</div>
/*
<div>
<p>{this.props.device.intensity}</p>
<Slider <Slider
min={0}
min={0} value={this.props.device.intensity} max={100} onChange={ (e, val) => {this.helper3(val)}} value={this.props.device.intensity}
max={100}
onChange={(e, val) => {
this.helper3(val);
}}
/> />
<input type="submit" value="increase" onClick={this.helper}/> <input type="submit" value="increase" onClick={this.helper} />
<input type="submit" value="decrease" onClick={this.helper2}/> <input type="submit" value="decrease" onClick={this.helper2} />
</div>; </div>*/
);
} }
} }
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id], device: state.devices[ownProps.id],
}); });

View file

@ -0,0 +1,69 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
position: relative;
margin-top: 10%;
width: 18rem;
height: 9rem;
background-color: #f7f7f7;
border-radius: 5px;
box-shadow: 10px 10px 30px 15px rgba(0, 0, 0, 0.247);
}
.open-container {
position: absolute;
width: 18rem;
background-color: #f79071;
border-radius: 5px;
}
.slider {
-webkit-appearance: none;
width: 9rem;
position: absolute;
left: 75%;
top: 50%;
transform: translateY(-50%) rotateZ(90deg);
background: transparent;
outline: none;
}
.slider::-webkit-slider-runnable-track {
-webkit-appearance: none;
height: 5px;
background-color: #1b1c1d;
border-radius: 50px;
cursor: pointer;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: #1b1c1d;
position: relative;
transition: all;
top: -5.5px;
}
.slider::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
.span-open {
-webkit-user-select: none;
font-family: "Lato";
font-weight: bold;
font-size: 3rem;
text-emphasis: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

View file

@ -0,0 +1,41 @@
// TODO Remove this!
import React, { Component } from "react";
import "./Curtains.css";
class Curtain extends Component {
constructor(props) {
super(props);
this.state = {
open: 0.6,
};
}
handleChange = (e) => {
this.setState({ open: e.target.value / 100 });
};
render() {
return (
<div className="container">
<div
className="open-container"
style={{ height: 9 * this.state.open + "rem" }}
></div>{" "}
<span className="span-open">
{Math.round(this.state.open * 100)}%
</span>
<input
onChange={this.handleChange}
value={this.state.open * 100}
className="slider"
type="range"
min="0"
max="100"
/>
</div>
);
}
}
export default Curtain;

View file

@ -35,9 +35,9 @@ class Device extends React.Component {
renderDeviceComponent() { renderDeviceComponent() {
switch (this.props.stateOrDevice.kind) { switch (this.props.stateOrDevice.kind) {
case "curtains": case "curtains":
return <Curtains tab={this.props.tab} id={this.props.id}/> return <Curtains tab={this.props.tab} id={this.props.id} />;
case "thermostat": case "thermostat":
return <Thermostat tab={this.props.tab} id={this.props.id}/> return <Thermostat tab={this.props.tab} id={this.props.id} />;
case "regularLight": case "regularLight":
return <Light tab={this.props.tab} id={this.props.id} />; return <Light tab={this.props.tab} id={this.props.id} />;
case "sensor": case "sensor":
@ -68,7 +68,9 @@ class Device extends React.Component {
<Grid.Column>{this.renderDeviceComponent()}</Grid.Column> <Grid.Column>{this.renderDeviceComponent()}</Grid.Column>
{this.props.tab === "Devices" ? ( {this.props.tab === "Devices" ? (
<Grid.Column textAlign="center"> <Grid.Column textAlign="center">
<Header as="h3">{this.props.stateOrDevice.name}</Header> <Header as="h3">
{this.props.stateOrDevice.name}
</Header>
<Button <Button
color="blue" color="blue"
icon icon
@ -92,11 +94,16 @@ class Device extends React.Component {
</Grid.Column> </Grid.Column>
) : ( ) : (
<Grid.Column textAlign="center"> <Grid.Column textAlign="center">
<Header as="h3">{this.props.stateOrDevice.name}</Header> <Header as="h3">
{this.props.stateOrDevice.name}
</Header>
</Grid.Column> </Grid.Column>
)} )}
<DeviceSettingsModal ref={this.modalRef} id={this.props.id} /> <DeviceSettingsModal
ref={this.modalRef}
id={this.props.id}
/>
</Grid> </Grid>
</Segment> </Segment>
); );

View file

@ -0,0 +1,38 @@
.slider-css {
-webkit-appearance: none;
width: 20rem;
font-family: "Lato";
position: absolute;
margin-top: 32%;
margin-left: 50%;
transform: translate(-50%, -50%);
}
.slider-css::-webkit-slider-thumb {
-webkit-appearance: none;
border: 5px solid #ffffff;
width: 18px;
height: 18px;
border-radius: 10px;
background-color: rgba(94, 246, 152, 1);
cursor: pointer;
box-shadow: 1px 1px 15px 2px rgba(0, 0, 0, 0.4);
margin-top: -7px;
}
.slider-css:focus {
-webkit-appearance: none;
outline: none;
}
.slider-css::-webkit-slider-runnable-track {
-webkit-appearance: none;
outline: none;
width: 100%;
height: 7px;
cursor: pointer;
box-shadow: 4.5px 4.5px 20px 1px rgba(0, 0, 0, 0.3);
background: white;
border-radius: 5px;
}

View file

@ -0,0 +1,62 @@
// TODO Remove this!
import React, { Component } from "react";
import {
stateTag,
container,
deviceName,
targetTemperature,
slider,
line,
stateTagContainer,
} from "./ThermostatStyle";
class Thermostat extends Component {
constructor(props) {
super(props);
this.state = {
currentTemperature: 10,
targetTemperature: 20,
state: "idle",
};
}
handleChange = (value) => {
let state = this.state.state;
if (this.state.currentTemperature > value) {
state = "cooling";
} else if (this.state.currentTemperature < value) {
state = "heating";
} else {
state = "idle"; // or heating, i don't know the difference
}
this.setState({ targetTemperature: value, state: state });
};
render() {
return (
<div style={container}>
<h3 style={deviceName}>{this.props.device.name}</h3>
<div style={line}></div>
<span style={targetTemperature}>
{this.state.targetTemperature}ºC
</span>
<input
type="range"
min="0"
max="40"
className="slider-css"
value={this.state.targetTemperature}
onChange={(event) => this.handleChange(event.target.value)}
id="targetTemperature"
/>
<div style={stateTagContainer}>
<span style={stateTag}>{this.state.state}</span>
</div>
</div>
);
}
}
export default Thermostat;

View file

@ -0,0 +1,73 @@
export const container = {
position: "relative",
width: "25rem",
height: "12rem",
boxShadow: "22px 18px 54px -7px rgba(102,102,102,1)",
borderRadius: "30px",
backgroundColor: "white",
};
export const line = {
width: "250px",
height: "47px",
borderBottom: "1px solid #646464",
position: "absolute",
left: "5%",
};
export const deviceName = {
fontFamily: "Lato",
position: "absolute",
marginTop: "5%",
marginLeft: "8%",
fontSize: "1rem",
fontWeight: "bold",
color: "#646464",
};
export const targetTemperature = {
fontFamily: "Lato",
position: "absolute",
marginTop: "20%",
marginLeft: "50%",
transform: "translate(-50%,-50%)",
fontSize: "3.5rem",
fontWeight: "bold",
color: "#646464",
};
export const slider = {
width: "25rem",
fontFamily: "Lato",
position: "absolute",
marginTop: "35%",
marginLeft: "50%",
transform: "translate(-50%,-50%)",
};
export const stateTagContainer = {
textAlign: "center",
position: "absolute",
width: "4rem",
height: "1rem",
marginTop: "40%",
marginLeft: "50%",
transform: "translate(-50%,-50%)",
padding: "0.5rem 4rem",
backgroundColor: "rgba(94,246,152,1)",
borderRadius: "50px",
};
export const stateTag = {
fontFamily: "Lato",
fontSize: "1.2rem",
color: "white",
textTransform: "uppercase",
};
export const toggle = {
position: "absolute",
top: "10%",
left: "35%",
transform: "rotate(-360deg)",
};

View file

@ -1,53 +1,67 @@
import React, {Component} from "react"; import React, { Component } from "react";
import { Checkbox } from "semantic-ui-react";
import { RemoteService } from "../../../remote"; import { RemoteService } from "../../../remote";
import { connect } from "react-redux"; import { connect } from "react-redux";
import "./Thermostat.css";
import {
stateTag,
container,
deviceName,
targetTemperature,
slider,
line,
toggle,
stateTagContainer,
} from "./ThermostatStyle";
//not quite working yet //not quite working yet
class Thermostats extends Component{ class Thermostats extends Component {
constructor (props){ constructor(props) {
super(props); super(props);
this.state = {targetTemperature: this.props.device.targetTemperature, this.state = {
internalSensorTemperature: this.props.device.internalSensorTemperature, targetTemperature: this.props.device.targetTemperature,
internalSensorTemperature: this.props.device
.internalSensorTemperature,
mode: this.props.device.mode, mode: this.props.device.mode,
measuredTemperature: this.props.device.measuredTemperature, measuredTemperature: this.props.device.measuredTemperature,
useExternalSensors: this.props.device.useExternalSensors, useExternalSensors: this.props.device.useExternalSensors,
timeout: null }; timeout: null,
this.setMode=this.setMode.bind(this); };
this.setTargetTemperature=this.setTargetTemperature.bind(this); this.setMode = this.setMode.bind(this);
this.setInternalSensorTemperature=this.setInternalSensorTemperature.bind(this); this.setTargetTemperature = this.setTargetTemperature.bind(this);
this.setInternalSensorTemperature = this.setInternalSensorTemperature.bind(
this
);
} }
//getters //getters
get getMode(){ get getMode() {
return this.props.device.mode; return this.props.device.mode;
} }
get getTargetTemperature(){ get getTargetTemperature() {
return this.props.device.targetTemperature; return this.props.device.targetTemperature;
} }
get getInternalSensorTemperature(){ get getInternalSensorTemperature() {
return this.props.device.internalSensorTemperature; return this.props.device.internalSensorTemperature;
} }
get getMeasuredTemperature(){ get getMeasuredTemperature() {
return this.props.device.measuredTemperature; return this.props.device.measuredTemperature;
} }
get getUseExternalSensors(){ get getUseExternalSensors() {
return this.props.device.useExternalSensors; return this.props.device.useExternalSensors;
} }
setMode(mode){ setMode(mode) {
if (this.state.timeout) { if (this.state.timeout) {
clearTimeout(this.state.timeout); clearTimeout(this.state.timeout);
} }
//i came to the conclusion that is not possible to set mode. //i came to the conclusion that is not possible to set mode.
this.mode="HEATING"; this.mode = "HEATING";
} }
onClickDevice = () => { onClickDevice = () => {
@ -57,16 +71,14 @@ class Thermostats extends Component{
.catch((err) => console.error("regular light update error", err)); .catch((err) => console.error("regular light update error", err));
}; };
//It seems to work //It seems to work
saveTargetTemperature(targetTemperature){ saveTargetTemperature(targetTemperature) {
this.props this.props
.saveDevice({ ...this.props.device, targetTemperature }) .saveDevice({ ...this.props.device, targetTemperature })
.catch((err) => console.error(" update error", err)); .catch((err) => console.error(" update error", err));
} }
setTargetTemperature(newTemp){ setTargetTemperature(newTemp) {
if (this.state.timeout) { if (this.state.timeout) {
clearTimeout(this.state.timeout); clearTimeout(this.state.timeout);
} }
@ -84,13 +96,13 @@ class Thermostats extends Component{
} }
//I have no idea why it doesn't want to update the temperature //I have no idea why it doesn't want to update the temperature
saveInternalSensorTemperature(internalSensorTemperature){ saveInternalSensorTemperature(internalSensorTemperature) {
this.props this.props
.saveDevice({ ...this.props.device, internalSensorTemperature }) .saveDevice({ ...this.props.device, internalSensorTemperature })
.catch((err) => console.error(" update error", err)); .catch((err) => console.error(" update error", err));
} }
setInternalSensorTemperature(newTemp){ setInternalSensorTemperature(newTemp) {
if (this.state.timeout) { if (this.state.timeout) {
clearTimeout(this.state.timeout); clearTimeout(this.state.timeout);
} }
@ -100,34 +112,89 @@ class Thermostats extends Component{
timeout: setTimeout(() => { timeout: setTimeout(() => {
this.saveInternalSensorTemperature(newTemp); this.saveInternalSensorTemperature(newTemp);
this.setState({ this.setState({
internalSensorTemperature: this.state.internalSensorTemperature, internalSensorTemperature: this.state
.internalSensorTemperature,
timeout: null, timeout: null,
}); });
}, 100), }, 100),
}); });
} }
helperMode=()=>{ helperMode = () => {
//this.setMode("HEATING"); //this.setMode("HEATING");
this.setTargetTemperature(20); this.setTargetTemperature(20);
//this.setInternalSensorTemperature(42); //this.setInternalSensorTemperature(42);
} };
render(){ handleChange = (value) => {
return <div><p>"mode is: "{this.props.device.mode}</p> this.setTargetTemperature(value);
<p>"internalsensortemperature is: "{this.props.device.internalSensorTemperature}</p> };
<p>"targetTemperature is: "{this.props.device.targetTemperature}</p>
<p>"measuredtemperature is: "{this.props.device.measuredTemperature}</p> render() {
return (
/*<div>
<p>"mode is: "{this.props.device.mode}</p>
<p>
"internalsensortemperature is: "
{this.props.device.internalSensorTemperature}
</p>
<p>
"targetTemperature is: "
{this.props.device.targetTemperature}
</p>
<p>
"measuredtemperature is: "
{this.props.device.measuredTemperature}
</p>
<p>{this.props.device.on}</p> <p>{this.props.device.on}</p>
<input type="submit" value="change targetTemperature" onClick={this.helperMode}/> <input
<input type="submit" value="robe" onClick={this.onClickDevice}/></div>; type="submit"
} value="change targetTemperature"
onClick={this.helperMode}
/>
<input
type="submit"
value="robe"
onClick={this.onClickDevice}
/>
</div>*/
<div style={container}>
<h3 style={deviceName}>{this.props.device.name}</h3>
<div style={line}></div>
<Checkbox
slider
style={toggle}
// TODO Manage the state here
onChange={(e, val) => console.log("CHANGE", val.checked)}
/>
<span style={targetTemperature}>
{this.props.device.targetTemperature}ºC
</span>
<input
type="range"
min="0"
max="40"
className="slider-css"
value={this.props.device.targetTemperature}
onChange={(event) => this.handleChange(event.target.value)}
id="targetTemperature"
/>
<div style={stateTagContainer}>
<span style={stateTag}>{this.props.device.mode}</span>
</div>
</div>
);
}
} }
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
device: state.devices[ownProps.id], device: state.devices[ownProps.id],
}); });
const ThermostatContainer = connect(mapStateToProps, RemoteService)(Thermostats); const ThermostatContainer = connect(
mapStateToProps,
RemoteService
)(Thermostats);
export default ThermostatContainer; export default ThermostatContainer;