Merge branch '82-scene-states-update' of lab.si.usi.ch:sa4-2020/the-sanmarinoes/frontend into 82-scene-states-update

# Conflicts:
#	smart-hut/src/components/dashboard/devices/Light.js
This commit is contained in:
Jacob Salvi 2020-04-25 17:50:05 +02:00
commit 2d04439948
5 changed files with 253 additions and 142 deletions

View file

@ -15,9 +15,10 @@ class ScenesPanel extends Component {
<Grid doubling columns={2} divided="vertically"> <Grid doubling columns={2} divided="vertically">
{!this.props.isActiveDefaultScene {!this.props.isActiveDefaultScene
? this.props.sceneStates.map((e, i) => { ? this.props.sceneStates.map((e, i) => {
console.log(this.props.sceneStates);
return ( return (
<Grid.Column key={i}> <Grid.Column key={i}>
<Device tab={this.props.tab} id={e} /> <Device tab={this.props.tab} id={e.id} />
</Grid.Column> </Grid.Column>
); );
}) })
@ -40,7 +41,8 @@ const mapStateToProps = (state, _) => ({
const stateArray = [ const stateArray = [
...state.scenes[state.active.activeScene].sceneStates, ...state.scenes[state.active.activeScene].sceneStates,
].sort(); ].sort();
return stateArray.map((id) => state.sceneStates[id]); console.log(stateArray);
return stateArray;
} else { } else {
return []; return [];
} }

View file

@ -13,114 +13,211 @@ import { connect } from "react-redux";
import DeviceSettingsModal from "./DeviceSettingsModal"; import DeviceSettingsModal from "./DeviceSettingsModal";
class Device extends React.Component { class Device extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.modalRef = React.createRef(); this.modalRef = React.createRef();
this.edit = this.edit.bind(this); this.edit = this.edit.bind(this);
this.resetSmartPlug = this.resetSmartPlug.bind(this); this.resetSmartPlug = this.resetSmartPlug.bind(this);
} }
edit() { edit() {
console.log("editing device with id=" + this.props.id); console.log("editing device with id=" + this.props.id);
this.modalRef.current.openModal(); this.modalRef.current.openModal();
} }
resetSmartPlug() { resetSmartPlug() {
this.props this.props
.smartPlugReset(this.props.id) .smartPlugReset(this.props.id)
.catch((err) => console.error(`Smart plug reset error`, err)); .catch((err) => console.error(`Smart plug reset error`, err));
} }
renderDeviceComponent() { renderDeviceComponent() {
console.log("check here") console.log(JSON.stringify(this.props.stateOrDevice));
console.log(this.props.stateOrDevice.kind) switch (
switch (this.props.stateOrDevice.kind) { this.props.tab === "Devices"
case "curtains": ? this.props.stateOrDevice.kind
return <Curtains tab={this.props.tab} id={this.props.id} />; : this.props.type
case "thermostat": ) {
return <Thermostat tab={this.props.tab} id={this.props.id} />; case "curtains":
case "regularLight":
return <Light tab={this.props.tab} id={this.props.id} />;
case "sensor":
return <Sensor tab={this.props.tab} id={this.props.id} />;
case "motionSensor":
return <Sensor tab={this.props.tab} id={this.props.id} />;
case "buttonDimmer":
return <ButtonDimmer tab={this.props.tab} id={this.props.id} />;
case "knobDimmer":
return <KnobDimmer tab={this.props.tab} id={this.props.id} />;
case "smartPlug":
return <SmartPlug tab={this.props.tab} id={this.props.id} />;
case "switch":
return <Switcher tab={this.props.tab} id={this.props.id} />;
case "dimmableLight":
return <Light id={this.props.id} />;
case "securityCamera":
return <Videocam id={this.props.id} />;
default:
throw new Error("Device type unknown");
}
}
render() {
return ( return (
<Segment> <Curtains
<Grid columns={2}> tab={this.props.tab}
<Grid.Column>{this.renderDeviceComponent()}</Grid.Column> sceneState={this.props.sceneState}
{this.props.tab === "Devices" ? ( id={this.props.id}
<Grid.Column textAlign="center"> />
<Header as="h3">
{this.props.stateOrDevice.name}
</Header>
<Button
color="blue"
icon
onClick={this.edit}
labelPosition="left"
>
<Icon name="pencil" />
Edit
</Button>
{this.props.stateOrDevice.kind === "smartPlug" ? (
<Button
color="orange"
icon
onClick={this.resetSmartPlug}
labelPosition="left"
>
<Icon name="undo" />
Reset
</Button>
) : null}
</Grid.Column>
) : (
<Grid.Column textAlign="center">
<Header as="h3">
{this.props.stateOrDevice.name}
</Header>
</Grid.Column>
)}
<DeviceSettingsModal
ref={this.modalRef}
id={this.props.id}
/>
</Grid>
</Segment>
); );
case "thermostat":
return (
<Thermostat
tab={this.props.tab}
sceneState={this.props.sceneStat}
id={this.props.stateOrDevice.id}
/>
);
case "regularLight":
return (
<Light
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "sensor":
return (
<Sensor
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "motionSensor":
return (
<Sensor
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "buttonDimmer":
return (
<ButtonDimmer
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "knobDimmer":
return (
<KnobDimmer
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "smartPlug":
return (
<SmartPlug
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "switch":
return (
<Switcher
tab={this.props.tab}
sceneState={this.props.sceneState}
id={this.props.stateOrDevice.id}
/>
);
case "dimmableLight":
return (
<Light
id={this.props.stateOrDevice.id}
sceneState={this.props.sceneState}
tab={this.props.tab}
/>
);
case "securityCamera":
return (
<Videocam
id={this.props.stateOrDevice.id}
sceneState={this.props.sceneState}
tab={this.props.tab}
/>
);
case "":
return "";
default:
throw new Error("Device type unknown");
} }
} }
render() {
return (
<Segment>
<Grid columns={2}>
<Grid.Column>{this.renderDeviceComponent()}</Grid.Column>
{this.props.tab === "Devices" ? (
<Grid.Column textAlign="center">
<Header as="h3">{this.props.stateOrDevice.name}</Header>
<Button
color="blue"
icon
onClick={this.edit}
labelPosition="left"
>
<Icon name="pencil" />
Edit
</Button>
{this.props.stateOrDevice.kind === "smartPlug" ? (
<Button
color="orange"
icon
onClick={this.resetSmartPlug}
labelPosition="left"
>
<Icon name="undo" />
Reset
</Button>
) : null}
</Grid.Column>
) : (
<Grid.Column textAlign="center">
<Header as="h3">
{this.props.stateOrDevice ? this.props.stateOrDevice.name : ""}
</Header>
</Grid.Column>
)}
</Grid>
</Segment>
);
}
}
/*
{this.props.stateOrDevice ?
<DeviceSettingsModal
ref={this.modalRef}
id={this.props.stateOrDevice.id}
/> :
""
}
*/
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
get stateOrDevice() { get stateOrDevice() {
if (state.active.activeTab === "Devices") { if (state.active.activeTab === "Devices") {
return state.devices[ownProps.id]; return state.devices[ownProps.id];
} else { } else {
const sceneState = state.sceneStates[ownProps.id]; console.log(
return state.devices[sceneState]; state.sceneStates,
} ownProps.id,
}, state.sceneStates[ownProps.id]
);
return state.sceneStates[ownProps.id];
}
},
get sceneState() {
if (state.active.activeTab === "Scenes") {
const array = [
...state.scenes[state.active.activeScene].sceneStates,
].sort();
const deviceState = array.filter((e) => e.id === ownProps.id)[0];
return deviceState;
} else {
return null;
}
},
get type() {
if (state.active.activeTab === "Scenes") {
const id = state.sceneStates[ownProps.id].deviceId;
console.log(id, state.devices[id].kind);
return state.devices[id].kind;
} else {
return null;
}
},
}); });
const DeviceContainer = connect(mapStateToProps, RemoteService)(Device); const DeviceContainer = connect(mapStateToProps, RemoteService)(Device);
export default DeviceContainer; export default DeviceContainer;

View file

@ -35,7 +35,10 @@ import { connect } from "react-redux";
class Light extends Component { class Light extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { intensity: this.props.stateOrDevice.intensity, timeout: null }; this.state = {
intensity: this.props.stateOrDevice.intensity,
timeout: null,
};
this.iconOn = "/img/lightOn.svg"; this.iconOn = "/img/lightOn.svg";
this.iconOff = "/img/lightOff.svg"; this.iconOff = "/img/lightOff.svg";
@ -44,8 +47,13 @@ class Light extends Component {
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
if (this.props.stateOrDevice.intensity !== prevProps.stateOrDevice.intensity) { if (
this.setState({ intensity: this.props.stateOrDevice.intensity, timeout: null }); this.props.stateOrDevice.intensity !== prevProps.stateOrDevice.intensity
) {
this.setState({
intensity: this.props.stateOrDevice.intensity,
timeout: null,
});
} }
} }
@ -59,12 +67,15 @@ class Light extends Component {
onClickDevice = () => { onClickDevice = () => {
const on = !this.turnedOn; const on = !this.turnedOn;
if(this.props.tab==="Devices"){ if (this.props.tab === "Devices") {
this.props this.props
.saveDevice({ ...this.props.stateOrDevice, on }) .saveDevice({ ...this.props.stateOrDevice, on })
.catch((err) => console.error("regular light update error", err)); .catch((err) => console.error("regular light update error", err));
}else{ } else {
this.props.updateState({ id: this.props.sceneState.id, on: on }, this.props.sceneState.kind); this.props.updateState(
{ id: this.props.sceneState.id, on: on },
this.props.sceneState.kind
);
} }
}; };
@ -93,12 +104,15 @@ class Light extends Component {
saveIntensity = () => { saveIntensity = () => {
const intensity = Math.round(this.state.intensity); const intensity = Math.round(this.state.intensity);
if(this.props.tab==="Devices"){ if (this.props.tab === "Devices") {
this.props this.props
.saveDevice({ ...this.props.stateOrDevice, intensity }) .saveDevice({ ...this.props.stateOrDevice, intensity })
.catch((err) => console.error("regular light update error", err)); .catch((err) => console.error("regular light update error", err));
}else{ } else {
this.props.updateState({ id: this.props.sceneState.id, intensity: intensity }, this.props.sceneState.kind); this.props.updateState(
{ id: this.props.sceneState.id, intensity: intensity },
this.props.sceneState.kind
);
} }
}; };
@ -156,11 +170,10 @@ class Light extends Component {
} }
const mapStateToProps = (state, ownProps) => ({ const mapStateToProps = (state, ownProps) => ({
get stateOrDevice(){ get stateOrDevice() {
if(state.active.activeTab==="Devices"){ if (state.active.activeTab === "Devices") {
return state.devices[ownProps.id]; return state.devices[ownProps.id];
}else{ } else {
const sceneState = state.sceneStates[ownProps.id];
return state.sceneStates[ownProps.id]; return state.sceneStates[ownProps.id];
} }
}, },

View file

@ -375,24 +375,24 @@ export const RemoteService = {
}, },
// //
updateState: (data,type)=>{ updateState: (data, type) => {
return (dispatch) => { return (dispatch) => {
let url; let url;
if(type=="dimmableState"){ if (type == "dimmableState") {
url="/dimmableState" url = "/dimmableState";
}else{ } else {
url="/switchableState" url = "/switchableState";
} }
return Endpoint["put"](url, {}, data) return Endpoint.put(url, {}, data)
.then((res) => { .then((res) => {
dispatch(actions.stateSave(res.data)); dispatch(actions.stateSave(res.data));
return res.data; return res.data;
}) })
.catch((err) => { .catch((err) => {
console.warn("Update device: ", data, "error: ", err); console.warn("Update device: ", data, "error: ", err);
throw new RemoteError(["Network error"]); throw new RemoteError(["Network error"]);
}); });
}; };
}, },

View file

@ -80,8 +80,8 @@ function reducer(previousState, action) {
}; };
const updateSceneStateProps = (state) => { const updateSceneStateProps = (state) => {
change.sceneStates[state.deviceId] = {}; change.sceneStates[state.id] = {};
change.sceneStates[state.deviceId] = { $set: state.deviceId }; change.sceneStates[state.id] = { $set: state.id };
}; };
switch (action.type) { switch (action.type) {
@ -104,6 +104,7 @@ function reducer(previousState, action) {
} }
break; break;
case "STATE_UPDATE": case "STATE_UPDATE":
console.log(action.sceneStates);
newState = previousState; newState = previousState;
change = null; change = null;
@ -129,9 +130,9 @@ function reducer(previousState, action) {
}; };
for (const sceneState of action.sceneStates) { for (const sceneState of action.sceneStates) {
if (!newState.sceneStates[sceneState.deviceId]) { if (!newState.sceneStates[sceneState.id]) {
change.sceneStates[sceneState.deviceId] = { change.sceneStates[sceneState.id] = {
$set: sceneState.deviceId, $set: sceneState,
}; };
} else { } else {
updateSceneStateProps(sceneState); updateSceneStateProps(sceneState);
@ -144,19 +145,17 @@ function reducer(previousState, action) {
change.scenes[sceneState.sceneId].sceneStates || {}; change.scenes[sceneState.sceneId].sceneStates || {};
const sceneStates = change.scenes[sceneState.sceneId].sceneStates; const sceneStates = change.scenes[sceneState.sceneId].sceneStates;
sceneStates.$add = sceneStates.$add || []; sceneStates.$add = sceneStates.$add || [];
sceneStates.$add.push(sceneState.deviceId); sceneStates.$add.push(sceneState);
} else { } else {
// room does not exist yet, so add to the list of pending // room does not exist yet, so add to the list of pending
// joins // joins
if (!change.pendingJoins.scenes[sceneState.sceneId]) { if (!change.pendingJoins.scenes[sceneState.sceneId]) {
change.pendingJoins.scenes[sceneState.sceneId] = { change.pendingJoins.scenes[sceneState.sceneId] = {
$set: new Set([sceneState.deviceId]), $set: new Set([sceneState]),
}; };
} else { } else {
change.pendingJoins.scenes[sceneState.sceneId].$set.add( change.pendingJoins.scenes[sceneState.sceneId].$set.add(sceneState);
sceneState.deviceId
);
} }
} }
} }