You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.0 KiB
120 lines
3.0 KiB
import React, { useState, useEffect } from 'react'; |
|
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; |
|
import axios from 'axios'; |
|
import moment from 'moment'; |
|
import './App.css'; |
|
|
|
function App() { |
|
const [data, setData] = useState(false); |
|
|
|
useEffect(() => { |
|
const get = async() => { |
|
try { |
|
const res = await axios.get('https://reg.t0.vc/solar.json'); |
|
setData(res.data); |
|
} catch (error) { |
|
setData(false); |
|
} |
|
}; |
|
|
|
get(); |
|
const interval = setInterval(get, 1000); |
|
return () => clearInterval(interval); |
|
}, []); |
|
|
|
const listen = () => { |
|
var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); |
|
var myArrayBuffer = audioCtx.createBuffer(2, audioCtx.sampleRate * 5, audioCtx.sampleRate); |
|
for (var channel = 0; channel < myArrayBuffer.numberOfChannels; channel++) { |
|
var nowBuffering = myArrayBuffer.getChannelData(channel); |
|
for (var i = 0; i < myArrayBuffer.length; i++) { |
|
nowBuffering[i] = data.history[i % data.history.length].total / 24000.0; |
|
} |
|
} |
|
var source = audioCtx.createBufferSource(); |
|
source.buffer = myArrayBuffer; |
|
source.connect(audioCtx.destination); |
|
source.start(); |
|
} |
|
|
|
return ( |
|
<div> |
|
{data ? |
|
<div> |
|
<ResponsiveContainer width='100%' height={300}> |
|
<LineChart data={data.history}> |
|
<XAxis |
|
dataKey='time' |
|
minTickGap={10} |
|
tickFormatter={timeStr => moment.utc(timeStr).format('HH:mm')} |
|
/> |
|
<YAxis /> |
|
<CartesianGrid strokeDasharray='3 3'/> |
|
<Tooltip |
|
labelFormatter={timeStr => 'Time: ' + moment.utc(timeStr).format('HH:mm')} |
|
/> |
|
|
|
<Line |
|
type='monotone' |
|
dataKey='total' |
|
name='Watts' |
|
stroke='#ff5900' |
|
strokeWidth={2} |
|
dot={false} |
|
animationDuration={1000} |
|
/> |
|
</LineChart> |
|
</ResponsiveContainer> |
|
|
|
<button onClick={listen}>Listen</button> |
|
|
|
{data.night ? |
|
<div className='container'> |
|
<p>The sun has set 😴</p> |
|
</div> |
|
: |
|
<div className='container'> |
|
<p>Total: {data.actual_total} W — {parseInt(data.actual_total / 5985 * 100)}%</p> |
|
|
|
<p>Today: {data.today_energy} kWh</p> |
|
|
|
<p>Updated: {data.timestamp.split(' ')[1]}</p> |
|
|
|
<p>Individual panels:</p> |
|
|
|
<div className='panels'> |
|
{Object.values(data.inverters).map((x, i) => |
|
<> |
|
<div |
|
className='panel' |
|
style={{ backgroundColor: `hsl(21, 100%, ${x.power[0]/315*50}%)` }} |
|
> |
|
<div className='panel-label'> |
|
{x.power[0]} |
|
</div> |
|
</div> |
|
|
|
{i != 2 && |
|
<div |
|
className='panel' |
|
style={{ backgroundColor: `hsl(21, 100%, ${x.power[1]/315*50}%)` }} |
|
> |
|
<div className='panel-label'> |
|
{x.power[1]} |
|
</div> |
|
</div> |
|
} |
|
</> |
|
)} |
|
</div> |
|
</div> |
|
} |
|
</div> |
|
: |
|
<p>Loading...</p> |
|
} |
|
</div> |
|
); |
|
} |
|
|
|
export default App;
|
|
|