Skip to content

Commit c720d78

Browse files
authored
Merge pull request #9 from GRIDAPPSD/der-updates
Der updates
2 parents 68ad763 + e6a7dd6 commit c720d78

34 files changed

+2777
-1074
lines changed

README.md

Lines changed: 563 additions & 68 deletions
Large diffs are not rendered by default.

gui/enddevices.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from dataclasses import fields
2+
3+
from nicegui import ui
4+
from session import backend_session, endpoint
5+
6+
import ieee_2030_5.models as m
7+
8+
columns = [
9+
{'name': 'property', 'label': 'Property', 'field': 'property', 'required': False},
10+
{'value': 'value', 'label': 'Value', 'field': 'property', 'required': False},
11+
]
12+
13+
def show_end_device(enddevice: m.EndDevice):
14+
ui.label(enddevice.href)
15+
16+
def show_list(enddevices: m.EndDeviceList):
17+
if len(enddevices.EndDevice) == 0:
18+
ui.label(f"No EndDevice in list. all={enddevices.all}, results={enddevices.results}")
19+
else:
20+
21+
for ed in enddevices.EndDevice:
22+
for fld in fields(ed):
23+
with ui.row():
24+
value = getattr(ed, fld.name)
25+
if value and fld.type in ('Optional[str]', 'str'):
26+
if isinstance(value, str):
27+
ui.label(f"{fld.name}, {value}, {fld.type}")
28+
else:
29+
ui.label(f"{fld.name}, {value.decode('utf-8')}, {fld.type}")
30+
# value = getattr(ed, fld.name)
31+
# if value and value.decode('utf-8'):
32+
# ui.label(f"{fld.name} => {value.decode('utf-8')}")
33+
34+
35+
def add_end_device():
36+
37+
def submit_end_device(id, pin):
38+
ui.label(f"Posted {id} and {pin}")
39+
40+
with ui.column():
41+
42+
id = ui.input(label="Id")
43+
pin = ui.input(label="Pin")
44+
ui.button("Save", on_click=lambda a: submit_end_device(id.value, pin.value))

gui/main.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python3
2+
3+
from enddevices import add_end_device, show_list
4+
from nicegui import ui
5+
from router import Router
6+
7+
from ieee_2030_5.utils import xml_to_dataclass
8+
9+
router = Router()
10+
11+
from session import backend_session, endpoint
12+
13+
14+
@router.add('/')
15+
async def show_one():
16+
ui.label('Content One').classes('text-2xl')
17+
18+
@router.add('/end-devices')
19+
async def show_end_devices():
20+
# resp = requests.get("https://127.0.0.1:7443/admin/enddevices",
21+
# cert=('/home/os2004/tls/certs/admin.pem', '/home/os2004/tls/private/admin.pem'),
22+
# verify="/home/os2004/tls/certs/ca.pem")
23+
resp = backend_session.get(endpoint("enddevices"))
24+
enddevices = xml_to_dataclass(resp.text)
25+
show_list(enddevices)
26+
27+
@router.add('/end-devices/add')
28+
async def add_enddevice():
29+
# resp = requests.get("https://127.0.0.1:7443/admin/enddevices",
30+
# cert=('/home/os2004/tls/certs/admin.pem', '/home/os2004/tls/private/admin.pem'),
31+
# verify="/home/os2004/tls/certs/ca.pem")
32+
#enddevices = xml_to_dataclass(resp.text)
33+
#show_list(enddevices)
34+
add_end_device()
35+
36+
37+
38+
39+
@router.add('/two')
40+
async def show_two():
41+
ui.label('Content Two').classes('text-2xl')
42+
43+
44+
@router.add('/three')
45+
async def show_three():
46+
ui.label('Content Three').classes('text-2xl')
47+
48+
49+
@ui.page('/') # normal index page (eg. the entry point of the app)
50+
@ui.page('/{_:path}') # all other pages will be handled by the router but must be registered to also show the SPA index page
51+
async def main():
52+
53+
with ui.header(elevated=True).style('background-color: #3874c8').classes('items-center justify-between'):
54+
ui.label('HEADER')
55+
56+
with ui.left_drawer(top_corner=True, bottom_corner=True).style('background-color: #d7e3f4'):
57+
with ui.column():
58+
ui.button("End Devices", on_click=lambda: router.open(show_end_devices)).classes('w-64')
59+
ui.button("Add End Device", on_click=lambda: router.open(add_enddevice)).classes('w-64')
60+
ui.button('One', on_click=lambda: router.open(show_one)).classes('w-64')
61+
ui.button('Two', on_click=lambda: router.open(show_two)).classes('w-64')
62+
ui.button('Three', on_click=lambda: router.open(show_three)).classes('w-64')
63+
64+
with ui.footer().style('background-color: #3874c8'):
65+
ui.label('FOOTER')
66+
67+
68+
69+
70+
# this places the content which should be displayed
71+
router.frame().classes('w-full p-4 bg-gray-100')
72+
73+
ui.run()

gui/router.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from typing import Awaitable, Callable, Dict, Union
2+
3+
from nicegui import background_tasks, ui
4+
from nicegui.dependencies import register_component
5+
6+
register_component('router_frame', __file__, 'router_frame.js')
7+
8+
9+
class Router():
10+
11+
def __init__(self) -> None:
12+
self.routes: Dict[str, Callable] = {}
13+
self.content: ui.element = None
14+
15+
def add(self, path: str):
16+
def decorator(func: Callable):
17+
self.routes[path] = func
18+
return func
19+
return decorator
20+
21+
def open(self, target: Union[Callable, str]):
22+
if isinstance(target, str):
23+
path = target
24+
builder = self.routes[target]
25+
else:
26+
path = {v: k for k, v in self.routes.items()}[target]
27+
builder = target
28+
29+
async def build():
30+
with self.content:
31+
await ui.run_javascript(f'history.pushState({{page: "{path}"}}, "", "{path}")', respond=False)
32+
result = builder()
33+
if isinstance(result, Awaitable):
34+
await result
35+
self.content.clear()
36+
background_tasks.create(build())
37+
38+
def frame(self) -> ui.element:
39+
self.content = ui.element('router_frame').on('open', lambda msg: self.open(msg['args']))
40+
return self.content

gui/router_frame.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export default {
2+
template: "<div><slot></slot></div>",
3+
mounted() {
4+
window.addEventListener("popstate", (event) => {
5+
if (event.state?.page) {
6+
this.$emit("open", event.state.page);
7+
}
8+
});
9+
const connectInterval = setInterval(async () => {
10+
if (window.socket.id === undefined) return;
11+
this.$emit("open", window.location.pathname);
12+
clearInterval(connectInterval);
13+
}, 10);
14+
},
15+
props: {},
16+
};

gui/session.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import requests
2+
3+
backend_session = requests.Session()
4+
5+
backend_session.cert = ('/home/os2004/tls/certs/admin.pem', '/home/os2004/tls/private/admin.pem')
6+
backend_session.verify = "/home/os2004/tls/certs/ca.pem"
7+
8+
def endpoint(endpoint: str) -> str:
9+
base_url = "https://127.0.0.1:7443/admin"
10+
return f"{base_url}/{endpoint}"

ieee_2030_5/__main__.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import sys
4545
import threading
4646
from argparse import ArgumentParser
47+
from multiprocessing import Process
4748
from pathlib import Path
4849
from time import sleep
4950

@@ -52,10 +53,9 @@
5253

5354
import ieee_2030_5.hrefs as hrefs
5455
from ieee_2030_5.certs import TLSRepository
55-
from ieee_2030_5.config import ServerConfiguration
56+
from ieee_2030_5.config import InvalidConfigFile, ServerConfiguration
5657
from ieee_2030_5.data.indexer import add_href
5758
from ieee_2030_5.flask_server import run_server
58-
from ieee_2030_5.models.adapters import InvalidConfigFile
5959
from ieee_2030_5.server.server_constructs import initialize_2030_5
6060

6161
_log = logging.getLogger()
@@ -121,6 +121,11 @@ def remove_stop_file():
121121
os.remove(pth)
122122

123123

124+
def _run_ui():
125+
126+
os.system('python gui/spa/main.py')
127+
128+
124129
def _main():
125130
parser = ArgumentParser()
126131

@@ -189,11 +194,15 @@ def _main():
189194

190195
#if not opts.production:
191196
try:
197+
# p = Process(target = _run_ui)
198+
# p.daemon = True
199+
# p.start()
200+
192201
run_server(config,
193202
tls_repo,
194203
end_devices,
195204
debug=opts.debug,
196-
use_reloader=False,
205+
use_reloader=True,
197206
use_debugger=True,
198207
threaded=False)
199208
except KeyboardInterrupt:

0 commit comments

Comments
 (0)