Implementing new features
This commit is contained in:
@@ -1 +1,2 @@
|
||||
from autodoc.autodoc import *
|
||||
from autodoc.configdb import *
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ import sys
|
||||
from argparse import ArgumentParser
|
||||
|
||||
import autodoc
|
||||
from configdb import ConfigDB
|
||||
|
||||
__version__ = "0.0.0"
|
||||
|
||||
@@ -78,7 +79,9 @@ def main():
|
||||
filename = args.output
|
||||
else:
|
||||
filename = os.path.splitext(os.path.basename(args.filename))[0]
|
||||
autodoc.document(filename, args, config)
|
||||
# autodoc.document(filename, args, config)
|
||||
|
||||
cfgdb = ConfigDB()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
Autodoc functions
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import common as doc
|
||||
from doc_state import *
|
||||
from doc_state_machine import doc_state_machine
|
||||
|
||||
|
||||
def __doc_app_state__(state, tab=" │ "):
|
||||
res = ""
|
||||
if "+Threads" in state:
|
||||
for i, tname in enumerate(state["+Threads"]):
|
||||
if tname[0] == "+":
|
||||
ch = "├─●" if i < len(state["+Threads"]) - 1 else "╰─●"
|
||||
res += f"{tab} {ch} {tname[1:]}\n"
|
||||
return res
|
||||
|
||||
|
||||
def __doc_application__(label, app):
|
||||
logging.info(f"Documenting real time application {label}")
|
||||
mdapp = f'\n## Real-time application: "{label[1:]}"\n\n'
|
||||
mdapp += f"Below are descrbed the states and threads of the real-time application {label[1:]}.\n"
|
||||
|
||||
mdapp += "\n"
|
||||
mdapp += "```\n"
|
||||
# mdapp += f'╭{"─"*(len(label)-1)}╮\n'
|
||||
# mdapp += f"│{label[1:]}│\n"
|
||||
# mdapp += f'╰┬{"─"*(len(label)-2)}╯\n'
|
||||
states = app["+States"]
|
||||
|
||||
for i, (state, obj) in enumerate(states.items()):
|
||||
if state[0] == "+":
|
||||
mdapp += f" - {state[1:]}\n"
|
||||
for thread in obj["+Threads"]:
|
||||
if thread[0] == "+":
|
||||
mdapp += f" - {thread[1:]}\n"
|
||||
ch = "├─▷" if i < len(states) - 1 else "╰─▷"
|
||||
tab = " │ " if i < len(states) - 1 else " "
|
||||
if label[0] == "+":
|
||||
mdapp += f" {ch} {label[1:]}\n"
|
||||
mdapp += __doc_app_state__(obj, tab)
|
||||
mdapp += "```\n"
|
||||
for label, obj in states.items():
|
||||
if label[0] == "+":
|
||||
mdapp += f'\n### State: "{label[1:]}"\n'
|
||||
mdapp += doc_state(label, obj, app)
|
||||
return mdapp
|
||||
|
||||
|
||||
def document(fname, args, config):
|
||||
"""Document MARTe object."""
|
||||
doc.set_path(os.path.join(args.destination, fname))
|
||||
doc.set_config(args)
|
||||
if not os.path.isdir(doc.path()):
|
||||
os.mkdir(doc.path())
|
||||
now = datetime.now() # current date and time
|
||||
today = now.strftime("%d/%m/%Y")
|
||||
mddoc = "---\n"
|
||||
mddoc += "toc: true\n"
|
||||
mddoc += f"title: {fname} Documentation\n"
|
||||
mddoc += "author: MARTe AutoDOC\n"
|
||||
mddoc += "titlepage: true\n"
|
||||
mddoc += f"date: {today}\n"
|
||||
mddoc += "geometry: margin=2cm\n"
|
||||
mddoc += "---\n\n"
|
||||
|
||||
mddoc += f"# {fname}\n"
|
||||
for label, obj in config.items():
|
||||
if "Class" in obj:
|
||||
if obj["Class"] == "RealTimeApplication":
|
||||
mddoc += __doc_application__(label, obj)
|
||||
if obj["Class"] == "StateMachine":
|
||||
mddoc += f'\n## State-Machine: "{label[1:]}"\n'
|
||||
mddoc += doc_state_machine(label[1:], obj)
|
||||
fpath = os.path.join(doc.path(), f"{fname}.md")
|
||||
outpath = os.path.join(doc.path(), fname)
|
||||
logging.info(f"Saving markdown: {fpath}")
|
||||
with open(fpath, "w") as file:
|
||||
file.write(mddoc)
|
||||
if doc.build():
|
||||
logging.info(f"Generating html: {outpath}.html")
|
||||
os.system(
|
||||
f"pandoc --css pandoc/styling.css --resource-path={doc.path()} --embed-resource --to html5 -s {fpath} -o {outpath}.html"
|
||||
)
|
||||
logging.info(f"Generating pdf: {outpath}.pdf")
|
||||
os.system(
|
||||
f"pandoc -H pandoc/disable_float.tex --resource-path={doc.path()} -s {fpath} -o {outpath}.pdf"
|
||||
)
|
||||
+5
-1
@@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
__PATH__ = "."
|
||||
__CONFIG__ = None
|
||||
@@ -29,12 +30,15 @@ def type_bytes_count(mtype):
|
||||
return 1
|
||||
|
||||
|
||||
def signal_byte_size(sig):
|
||||
def signal_byte_size(parent_id, sig_id, sig):
|
||||
noe = 1 if "NumberOfElements" not in sig else int(sig["NumberOfElements"])
|
||||
nod = 1 if "NumberOfDimensions" not in sig else int(sig["NumberOfDimensions"])
|
||||
nod = nod if nod > 0 else 1
|
||||
noe = noe if noe > 0 else 1
|
||||
nos = 1 if "Samples" not in sig else int(sig["Samples"])
|
||||
if "Type" not in sig:
|
||||
logging.fatal(f"no type defined for signal {parent_id}.{sig_id}")
|
||||
sys.exit(1)
|
||||
bytes = type_bytes_count(sig["Type"])
|
||||
tot = noe * nod * nos
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
from re import search
|
||||
|
||||
from MARTe.StandardParser import logging
|
||||
|
||||
|
||||
class ConfigDB:
|
||||
def __new__(cls):
|
||||
if not hasattr(cls, "instance"):
|
||||
cls.instance = super(ConfigDB, cls).__new__(cls)
|
||||
return cls.instance
|
||||
|
||||
def __init__(self):
|
||||
ConfigDB.__INST__ = self
|
||||
self.__db__ = {}
|
||||
|
||||
def get(self, path: str):
|
||||
ipath = path.split(".")
|
||||
obj = self.__db__
|
||||
for p in ipath:
|
||||
if p in obj:
|
||||
obj = obj[p]
|
||||
else:
|
||||
logging.error(f"no key {p} found for {path}")
|
||||
return None
|
||||
return obj
|
||||
|
||||
def insert(self, key: dict, obj):
|
||||
pass
|
||||
|
||||
|
||||
class MARTeOBJ:
|
||||
def __init__(self, fname, id, cfg):
|
||||
self.__name__ = id
|
||||
self.__mcls__ = cfg["Class"]
|
||||
self.__struct__ = {}
|
||||
for key, itm in cfg.items():
|
||||
if key != "Class":
|
||||
if isinstance(itm, dict) and "Class" in itm:
|
||||
self.__struct__[key] = MARTeOBJ(fname, key, itm)
|
||||
else:
|
||||
self.__struct__[key] = itm
|
||||
|
||||
def pretty_print(self, spacing=""):
|
||||
str = f"{spacing}{self.__name__}[{self.__mcls__}]:\n"
|
||||
for key, itm in self.__struct__.items():
|
||||
if isinstance(itm, MARTeOBJ):
|
||||
str += itm.pretty_print(spacing + " ")
|
||||
else:
|
||||
str += f"{spacing} {key}: {itm}\n"
|
||||
return str
|
||||
|
||||
def __repr__(self) -> str:
|
||||
str = f"{self.__name__}[{self.__mcls__}]:\n"
|
||||
for key, itm in self.__struct__.items():
|
||||
str += f" {key}: {itm}\n"
|
||||
return str
|
||||
|
||||
|
||||
def parse_config(fname: str, config: dict):
|
||||
for key, obj in config.items():
|
||||
ConfigDB().insert(key, obj)
|
||||
@@ -111,7 +111,7 @@ def __doc_iogam__(id, obj, edges, thread):
|
||||
while input_size <= output_size and in_i < len(inputs):
|
||||
in_label = input_names[in_i]
|
||||
input = inputs[in_label]
|
||||
input_size += doc.signal_byte_size(input)
|
||||
input_size += doc.signal_byte_size(id, in_label, input)
|
||||
in_i += 1
|
||||
alias = doc.signal_alias(in_label, input)
|
||||
mtype = doc.signal_type(input)
|
||||
@@ -134,7 +134,7 @@ def __doc_iogam__(id, obj, edges, thread):
|
||||
while output_size < input_size and out_i < len(outputs):
|
||||
out_label = output_names[out_i]
|
||||
output = outputs[out_label]
|
||||
output_size += doc.signal_byte_size(output)
|
||||
output_size += doc.signal_byte_size(id, out_label, output)
|
||||
out_i += 1
|
||||
alias = doc.signal_alias(out_label, output)
|
||||
mtype = doc.signal_type(output)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"$App": {
|
||||
"Class": "RealTimeApplication",
|
||||
"+Data": {
|
||||
"Class": "ReferenceContainer",
|
||||
"+RTTimer": {
|
||||
"Class": "LinuxTimer",
|
||||
"SleepNature": "Busy",
|
||||
"CPUMask": 2,
|
||||
"Locked": 1,
|
||||
"Signals": {
|
||||
"Counter": {
|
||||
"Type": "uint32"
|
||||
},
|
||||
"Time": {
|
||||
"Type": "uint32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"+Timing": {
|
||||
"Class": "TimingDataSource",
|
||||
"Locked": 1
|
||||
},
|
||||
"+DDB0": {
|
||||
"Class": "GAMDataSource",
|
||||
"Locked": 1,
|
||||
"Signals": {
|
||||
"Time": {
|
||||
"Type": "uint32"
|
||||
},
|
||||
"Times": {
|
||||
"Type": "uint32",
|
||||
"NumberOfDimensions": 1,
|
||||
"NumberOfElements": 3
|
||||
},
|
||||
"Amplitudes": {
|
||||
"Type": "float32",
|
||||
"NumberOfDimensions": 1,
|
||||
"NumberOfElements": 3
|
||||
}
|
||||
}
|
||||
},
|
||||
"+EpicsIn": {
|
||||
"Class": "EPICSCA::EPICSCAInput",
|
||||
"Locked": 1,
|
||||
"Signals": {
|
||||
"Amplitude": {
|
||||
"Type": "float32",
|
||||
"PVName": "Amplitude"
|
||||
},
|
||||
"Frequency": {
|
||||
"Type": "float32",
|
||||
"PVName": "Frequency"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DefaultDataSource": "DDB0",
|
||||
"+Logger": {
|
||||
"Class": "OnChangeLoggerDataSource",
|
||||
"Locked": 1,
|
||||
"Signals": {
|
||||
"Times": {
|
||||
"Type": "uint32",
|
||||
"NumberOfDimensions": 1,
|
||||
"NumberOfElements": 3
|
||||
},
|
||||
"Amplitudes": {
|
||||
"Type": "float32",
|
||||
"NumberOfDimensions": 1,
|
||||
"NumberOfElements": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"+Functions": {
|
||||
"+TimerGAM": {
|
||||
"Class": "IOGAM",
|
||||
"InputSignals": {
|
||||
"Time": {
|
||||
"Frequency": 100,
|
||||
"DataSource": "RTTimer",
|
||||
"Type": "uint32",
|
||||
"Alias": "Time"
|
||||
}
|
||||
},
|
||||
"OutputSignals": {
|
||||
"Time": {
|
||||
"DataSource": "DDB0",
|
||||
"Type": "uint32",
|
||||
"Alias": "Time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"+Chai": {
|
||||
"Class": "ChaiGAM",
|
||||
"Code": "global g = 4;\nfun() {\n\tg = g + 1;\n\ty[0] = -A;\n \ty[1] = A;\n\ty[2] = -A;\n\tt[0] = g;\n\tif (freq <= 0) {\n\t\tt[1] = 0;\n\t\tt[2] = 0;\n\t} else {\n\t\tt[1] = int(5e5 / freq);\n\t\tt[2] = int(1e6 / freq);\n\t}\n}",
|
||||
"InputSignals": {
|
||||
"A": {
|
||||
"DataSource": "EpicsIn",
|
||||
"Type": "float32",
|
||||
"Alias": "Amplitude"
|
||||
},
|
||||
"freq": {
|
||||
"DataSource": "EpicsIn",
|
||||
"Type": "float32",
|
||||
"Alias": "Frequency"
|
||||
}
|
||||
},
|
||||
"OutputSignals": {
|
||||
"t": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "DDB0",
|
||||
"Type": "uint32",
|
||||
"Alias": "Times"
|
||||
},
|
||||
"y": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "DDB0",
|
||||
"Type": "float32",
|
||||
"Alias": "Amplitudes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Class": "ReferenceContainer",
|
||||
"+LogGAM": {
|
||||
"Class": "IOGAM",
|
||||
"InputSignals": {
|
||||
"t": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "DDB0",
|
||||
"Type": "uint32",
|
||||
"Alias": "Times"
|
||||
},
|
||||
"y": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "DDB0",
|
||||
"Type": "float32",
|
||||
"Alias": "Amplitudes"
|
||||
}
|
||||
},
|
||||
"OutputSignals": {
|
||||
"times": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "Logger",
|
||||
"Type": "uint32",
|
||||
"Alias": "Times"
|
||||
},
|
||||
"amplitudes": {
|
||||
"NumberOfElements": 3,
|
||||
"NumberOfDimensions": 1,
|
||||
"DataSource": "Logger",
|
||||
"Type": "float32",
|
||||
"Alias": "Amplitudes"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"+States": {
|
||||
"Class": "ReferenceContainer",
|
||||
"+Exec": {
|
||||
"Class": "RealTimeState",
|
||||
"+Threads": {
|
||||
"+Comm": {
|
||||
"Class": "RealTimeThread",
|
||||
"CPUs": 1,
|
||||
"Functions": [
|
||||
"TimerGAM",
|
||||
"Chai",
|
||||
"LogGAM"
|
||||
]
|
||||
},
|
||||
"Class": "ReferenceContainer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"+Scheduler": {
|
||||
"Class": "GAMScheduler",
|
||||
"TimingDataSource": "Timing"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
packages:
|
||||
core:
|
||||
description: "MARTe2 Core Package"
|
||||
namespace: ""
|
||||
url: "https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2"
|
||||
datasources:
|
||||
GAMDataSource:
|
||||
brief: "DataSource implementation for the exchange of signals between GAM components."
|
||||
prameters:
|
||||
HeapName:
|
||||
type: "string"
|
||||
comment: "GetStandardHeap() if not defined"
|
||||
default: ""
|
||||
AllowNoProducer:
|
||||
type: "bool"
|
||||
mandatory: false
|
||||
default: 0
|
||||
ResetUnusedVariableAtStateChange:
|
||||
type: "bool"
|
||||
mandatory: false
|
||||
default: 1
|
||||
Signals:
|
||||
mode: "any"
|
||||
components:
|
||||
description: "MARTe2 Components"
|
||||
url: "https://vcis-gitlab.f4e.europa.eu/aneto/MARTe2-components"
|
||||
namespace: ""
|
||||
@@ -0,0 +1,177 @@
|
||||
import gi
|
||||
|
||||
gi.require_version("Gtk", "3.0")
|
||||
gi.require_version("Gdk", "3.0")
|
||||
|
||||
from gi.repository import Gdk, Gtk
|
||||
|
||||
|
||||
class ControlPanel(Gtk.Box):
|
||||
def __init__(self):
|
||||
super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
# Place the control panel in the top right
|
||||
self.set_halign(Gtk.Align.END)
|
||||
self.set_valign(Gtk.Align.START)
|
||||
|
||||
# Add the .control-panel CSS class to this widget
|
||||
context = self.get_style_context()
|
||||
context.add_class("control-panel")
|
||||
|
||||
def add_group(self, group):
|
||||
self.pack_start(group, False, False, 0)
|
||||
|
||||
|
||||
class ControlPanelGroup(Gtk.Expander):
|
||||
def __init__(self, title: str):
|
||||
Gtk.Expander.__init__(self, label=title)
|
||||
self._inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||
|
||||
# Set the size request to 200 pixels wide
|
||||
self.set_size_request(200, -1)
|
||||
|
||||
# Add a bit of margin after the header
|
||||
self._inner.set_margin_top(5)
|
||||
|
||||
self.add(self._inner)
|
||||
|
||||
def add_row(self, widget):
|
||||
self._inner.pack_start(widget, False, False, 0)
|
||||
|
||||
|
||||
class MyControlPanel(ControlPanel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._first_panel = ControlPanelGroup("Some Buttons")
|
||||
self._first_panel.add_row(Gtk.Button(label="Button 1"))
|
||||
self._first_panel.add_row(Gtk.Button(label="Button 2"))
|
||||
self.add_group(self._first_panel)
|
||||
|
||||
self._second_panel = ControlPanelGroup("Extra Settings")
|
||||
self._second_panel.add_row(Gtk.Button(label="Button 3"))
|
||||
self._second_panel.add_row(Gtk.Button(label="Button 4"))
|
||||
self._second_panel.add_row(Gtk.CheckButton.new_with_label("First checkbox"))
|
||||
self._second_panel.add_row(Gtk.CheckButton.new_with_label("Second checkbox"))
|
||||
|
||||
combo = Gtk.ComboBoxText()
|
||||
combo.append("first", "First Choice")
|
||||
combo.append("second", "Second Choice")
|
||||
combo.append("third", "Third Choice")
|
||||
combo.append("forth", "This one is quite long")
|
||||
combo.set_active_id("first")
|
||||
self._second_panel.add_row(combo)
|
||||
|
||||
self.add_group(self._second_panel)
|
||||
|
||||
|
||||
class MapEditor(Gtk.DrawingArea):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.set_events(
|
||||
Gdk.EventMask.BUTTON_PRESS_MASK
|
||||
| Gdk.EventMask.BUTTON_RELEASE_MASK
|
||||
| Gdk.EventMask.POINTER_MOTION_MASK
|
||||
)
|
||||
|
||||
self._camera_x = 0 # The X coordinate of the camera
|
||||
self._camera_y = 0 # The Y coordinate of the camera
|
||||
self._mouse_x = 0 # The X coordinate of the pointer
|
||||
self._mouse_y = 0 # The Y coordinate of the pointer
|
||||
self._button = None # The currently held mouse button
|
||||
|
||||
# Connect to the draw and mouse events
|
||||
self.connect("draw", self.on_draw)
|
||||
self.connect("button-press-event", self.on_button_press_event)
|
||||
self.connect("button-release-event", self.on_button_release_event)
|
||||
self.connect("motion-notify-event", self.on_motion_notify_event)
|
||||
|
||||
def on_button_press_event(self, widget, event):
|
||||
self._mouse_x = event.x
|
||||
self._mouse_y = event.y
|
||||
self._button = event.button
|
||||
|
||||
def on_button_release_event(self, widget, event):
|
||||
self._mouse_x = 0
|
||||
self._mouse_y = 0
|
||||
self._button = None
|
||||
|
||||
def on_motion_notify_event(self, widget, event):
|
||||
if self._button == Gdk.BUTTON_SECONDARY:
|
||||
self._camera_x += event.x - self._mouse_x
|
||||
self._camera_y += event.y - self._mouse_y
|
||||
self._mouse_x = event.x
|
||||
self._mouse_y = event.y
|
||||
self.queue_draw()
|
||||
|
||||
def on_draw(self, widget, context):
|
||||
# Get the width and height of the widget
|
||||
width = self.get_allocated_width()
|
||||
height = self.get_allocated_height()
|
||||
|
||||
# Render a rectangle for the background of the editor
|
||||
context.set_source_rgb(0.11, 0.11, 0.11)
|
||||
context.rectangle(0, 0, width, height)
|
||||
context.fill()
|
||||
|
||||
# Render our grids
|
||||
context.set_line_width(1)
|
||||
for color, step in [(0.2, 10), (0.3, 100)]:
|
||||
context.set_source_rgb(color, color, color)
|
||||
y = int(self._camera_y % step) + 0.5
|
||||
while y < height:
|
||||
context.move_to(0, y)
|
||||
context.line_to(width, y)
|
||||
y += step
|
||||
x = int(self._camera_x % step) + 0.5
|
||||
while x < width:
|
||||
context.move_to(x, 0)
|
||||
context.line_to(x, height)
|
||||
x += step
|
||||
context.stroke()
|
||||
|
||||
|
||||
class MainWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.set_title("Collapsible Controls Overlay Demo")
|
||||
|
||||
# Set the default window size to 800x800
|
||||
self.set_default_size(800, 800)
|
||||
# When our window is destroyed, exit the main event loop
|
||||
self.connect("destroy", Gtk.main_quit)
|
||||
|
||||
# Create our map editor and control panel instances
|
||||
self._editor = MapEditor()
|
||||
self._controls = MyControlPanel()
|
||||
|
||||
# Create the overlay widget
|
||||
self._overlay = Gtk.Overlay()
|
||||
|
||||
# Add our editor and control panel as overlays
|
||||
self._overlay.add_overlay(self._editor)
|
||||
self._overlay.add_overlay(self._controls)
|
||||
|
||||
# Add the overlay as the immediate child of the window
|
||||
self.add(self._overlay)
|
||||
|
||||
|
||||
def install_css():
|
||||
screen = Gdk.Screen.get_default()
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_data(
|
||||
b"""
|
||||
.control-panel {
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
padding: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
"""
|
||||
)
|
||||
Gtk.StyleContext.add_provider_for_screen(screen, provider, 600)
|
||||
|
||||
|
||||
install_css()
|
||||
window = MainWindow()
|
||||
window.show_all()
|
||||
Gtk.main()
|
||||
|
||||
Reference in New Issue
Block a user