sensor_demo / app.py
andrewlee1807's picture
update
e99c10f
# Note: Main must be imported even though it is not used.
from h2o_wave import Q, ui, app, main, data, on
import numpy as np
import pandas as pd
import random
import time
import asyncio
NUMBER_SENSORS = 4
LIMIT_LEN_SHOWING = 20
REALTIME_UPDATE = 5 # seconds
list_data = []
line_charts_data = [] # [(sensor_id, [data]), ...]
for i in range(NUMBER_SENSORS):
line_charts_data.append((i, []))
start_year = 1991
while True:
for i in range(NUMBER_SENSORS):
random_value = random.uniform(1, 50) # Generate a random value between 1 and 50
value = (str(start_year), random_value)
line_charts_data[i][1].append(value)
start_year += 1
if start_year == 2021:
break
async def update_value(q: Q):
while True:
time.sleep(REALTIME_UPDATE)
# TODO: Update realtime values for current stats cards
# value_counts = random.randint(0, 100)
# percentages = random.random()
percentages = np.random.random(NUMBER_SENSORS)
value_counts = np.random.randint(0, 100, NUMBER_SENSORS)
show_multiple_stats_cards(q, value_counts, percentages)
await q.page.save()
async def api_get_data():
global list_data, line_charts_data, start_year
while True:
for i in range(NUMBER_SENSORS):
random_value = random.uniform(1, 50) # Generate a random value between 1 and 50
value = (str(start_year), random_value)
line_charts_data[i][1].append(value)
start_year += 1
await asyncio.sleep(REALTIME_UPDATE)
async def update_charts(q: Q):
global line_charts_data
while True:
time.sleep(REALTIME_UPDATE)
for sensor_data in line_charts_data:
sensor_id = str(sensor_data[0])
data = sensor_data[1]
limites_showing_data = LIMIT_LEN_SHOWING if len(data) > LIMIT_LEN_SHOWING else len(data)
show_line_graph(q, sensor_id, data[-limites_showing_data:])
percentages = np.random.random(NUMBER_SENSORS)
value_counts = np.random.randint(0, 100, NUMBER_SENSORS)
show_multiple_stats_cards(q, value_counts, percentages)
await q.page.save()
def on_startup():
print('App started!')
def on_shutdown():
print('App stopped!')
task_data = asyncio.create_task(api_get_data())
@app('/', on_startup=on_startup, on_shutdown=on_shutdown, mode='broadcast')
async def sever(q: Q):
apply_layout(q)
show_homepage(q)
# show_histograms(q, df, index=[1, 7, 8])
# await update_value(q)
await update_charts(q)
# await q.page.save()
def show_homepage(q: Q):
q.page['header'] = ui.header_card(
box=ui.box('header', width='100%', height='86px'),
icon='Video360Generic',
icon_color='White',
title='AgroTrack Application',
subtitle='๋‹ด์–‘๋†์—…๊ธฐ์ˆ ์„ผํ„ฐ')
q.page['footer'] = ui.footer_card(
box='footer',
caption='Copyright (C) [AISeed](https://sprout-fibre-be6.notion.site/AISEED-40e62bb70c024a2c974c0a7051aca86f?pvs=4) Designed by [Blackhole](https://github.com/andrewlee1807/)')
def apply_layout(q: Q):
q.page['meta'] = ui.meta_card(box='', theme='oceanic', title="SmartFarm's Sensor Dashboard",
layouts=[
ui.layout(
breakpoint='xl',
width='1600px',
zones=[
ui.zone('header'),
ui.zone('body', direction=ui.ZoneDirection.ROW, zones=[
ui.zone('content', direction=ui.ZoneDirection.COLUMN, zones=[
ui.zone('section1'),
ui.zone('top', size='300px', direction=ui.ZoneDirection.ROW),
ui.zone('section2'),
ui.zone('bottom', direction=ui.ZoneDirection.ROW),
ui.zone('chart1', direction=ui.ZoneDirection.ROW),
]),
]),
ui.zone('footer')
]),
])
## Making stats cards
def make_stats_card_data(q: Q, column):
value_counts = column.value_counts()
total = value_counts.sum()
return value_counts[1], total
# Randomly generate data for stats cards: percentage and value (randomly generated)
def show_stats_card(q: Q, name, value_count, percentage):
q.page['stat_' + name] = ui.tall_gauge_stat_card(
box=ui.box('top', width='12.5%'),
title='Number of houses with ' + name,
value='={{intl one}}',
aux_value='={{intl perc style="percent" minimum_fraction_digits=2 maximum_fraction_digits=2 }}',
progress=percentage,
data=dict(one=int(value_count), perc=float(percentage)),
plot_color='$red'
)
def show_multiple_stats_cards(q: Q, value_counts, percentages):
for i, j in enumerate(zip(value_counts, percentages)):
name = "feature_" + str(i)
value_count, percentage = j
show_stats_card(q, name, value_count, percentage)
# Making histograms
def make_histogram_data(values):
count, division = np.histogram(values)
return [(x, y) for x, y in zip(division.tolist(), count.tolist())]
def show_histogram(q: Q, values, variable_name, index):
q.page['feat' + str(index)] = ui.tall_series_stat_card(
box=ui.box('bottom', width='25%'),
title='Linear tall series' + variable_name,
value='=${{intl qux minimum_fraction_digits=2 maximum_fraction_digits=2}}',
aux_value='={{intl quux style="percent" minimum_fraction_digits=1 maximum_fraction_digits=1}}',
data=dict(qux=800, quux=80 / 100),
plot_type='area',
plot_category='foo',
plot_value='qux',
plot_color='$yellow',
plot_data=data('foo qux', 3, rows=[[90, 0.9], [50, 0.5], [80, 0.8]]),
plot_zero_value=0,
plot_curve='smooth',
)
def show_line_graph(q: Q, name, data_rows):
q.page['section2'] = ui.section_card(box='section2',
title='Plot of the data',
subtitle='')
position = 'bottom' if int(name) < 2 else 'chart1'
q.page[name] = ui.plot_card(
box=ui.box(position, width='50%'),
title='Sensor ' + name,
animate=True,
data=data('time value', LIMIT_LEN_SHOWING, rows=data_rows),
events=['select_marks'],
plot=ui.plot([
ui.mark(type='line',
x_scale='time',
x='=time',
y='=value',
y_min=0, interactive=True),
ui.mark(type='point',
x='=time',
# x='={{intl year type="time" month="numeric" day="numeric" hour="numeric" minute="numeric" hourCycle="h24" }}',
y='=value',
size=4,
fill_color='#FFFF28',
x_title='Time', y_title='Value',
interactive=True),
]),
)
@on('select_marks')
async def on_marks_selected(q: Q):
print("Click")