-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1d5ec79
commit 5488450
Showing
85 changed files
with
1,607 additions
and
2,421 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,3 +136,4 @@ dmypy.json | |
|
||
# Log File | ||
*.log | ||
*.csv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Python: Module", | ||
"type": "python", | ||
"request": "launch", | ||
"module": "tests.test_devstone", | ||
// "env": {"PYTHONPATH": "${workspaceFolder}/libs/"} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"python.autoComplete.extraPaths": ["${workspaceFolder}/xdevs"], | ||
"python.testing.cwd": "${workspaceFolder/xdevs}", | ||
"python.analysis.include": [ | ||
"${workspaceFolder}/xdevs" | ||
], | ||
"python.analysis.extraPaths": [ | ||
"${workspaceFolder}" | ||
], | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
[build-system] | ||
requires = ["setuptools >= 61.0"] | ||
build-backend = "setuptools.build_meta" | ||
|
||
[project] | ||
name = "xdevs" | ||
version = "3.0.0" | ||
requires-python = ">=3.8" | ||
authors = [ | ||
{name = "Román Cárdenas"}, | ||
{name = "Óscar Fernández Sebastián"}, | ||
{name = "Kevin Henares"}, | ||
{name = "José L. Risco-Martín"}, | ||
] | ||
maintainers = [ | ||
{name = "Román Cárdenas", email = "[email protected]"}, | ||
] | ||
description = "xDEVS M&S framework" | ||
readme = "README.md" | ||
license = {file = "LICENSE.txt"} | ||
keywords = ["DEVS", "modeling", "simulation"] | ||
|
||
[project.optional-dependencies] | ||
sql = ["sqlalchemy"] | ||
elasticsearch = ["elasticsearch"] | ||
mqtt = ["paho-mqtt"] | ||
|
||
[project.urls] | ||
Homepage = "https://github.com/iscar-ucm/xdevs" | ||
Documentation = "https://github.com/iscar-ucm/xdevs" | ||
Repository = "https://github.com/iscar-ucm/xdevs.py.git" | ||
"Bug Tracker" = "https://github.com/iscar-ucm/xdevs.py/issues" | ||
Changelog = "https://github.com/iscar-ucm/xdevs.py/blob/main/CHANGELOG.md" | ||
|
||
[project.entry-points."xdevs.transducers"] | ||
csv = "xdevs.plugins.transducers.csv:CSVTransducer" | ||
sql = "xdevs.plugins.transducers.sql:SQLTransducer" | ||
elasticsearch = "xdevs.plugins.transducers.elasticsearch:ElasticsearchTransducer" | ||
|
||
[project.entry-points."xdevs.input_handlers"] | ||
function = "xdevs.plugins.input_handlers.function:CallableFunction" | ||
csv = "xdevs.plugins.input_handlers.csv:CSVInputHandler" | ||
tcp = "xdevs.plugins.input_handlers.tcp:TCPInputHandler" | ||
mqtt = "xdevs.plugins.input_handlers.mqtt:MQTTInputHandler" | ||
|
||
[project.entry-points."xdevs.output_handlers"] | ||
csv = "xdevs.plugins.output_handlers.csv:CSVOutputHandler" | ||
tcp = "xdevs.plugins.output_handlers.tcp:TCPOutputHandler" | ||
mqtt = "xdevs.plugins.output_handlers.mqtt:MQTTOutputHandler" | ||
|
||
[project.entry-points."xdevs.components"] | ||
generator = "xdevs.examples.gpt.gpt:Generator" | ||
transducer = "xdevs.examples.gpt.gpt:Transducer" | ||
processor = "xdevs.examples.gpt.gpt:Processor" | ||
gpt = "xdevs.examples.gpt.gpt:Gpt" | ||
ef = "xdevs.examples.gpt.efp:Ef" | ||
efp = "xdevs.examples.gpt.efp:Efp" | ||
|
||
[project.entry-points."xdevs.wrappers"] | ||
pypdevs = "xdevs.plugins.wrappers.pypdevs:PyPDEVSWrapper" | ||
|
||
[tool.setuptools] | ||
include-package-data = false | ||
|
||
[tool.setuptools.packages.find] | ||
include = ["xdevs*"] | ||
exclude = ["xdevs.tests*"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .handler import InputHandler, OutputHandler | ||
from .transducer import Transducer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import queue | ||
import sys | ||
from abc import ABC, abstractmethod | ||
from typing import Callable, Any | ||
|
||
|
||
class Connector: | ||
def __init__(self, conections: dict[str, str]): | ||
""" | ||
Función para conectar de forma correcta los puertos (que usen protocolo MQTT) | ||
:param conections: dict[key: str, value: str]. Donde la key es el puerto de al que me quiero conectar y el | ||
value es el puerto de mi acoplado. | ||
""" | ||
self.connections: dict[str, str] = conections | ||
|
||
def input_handler(self, port: str): | ||
if self.connections is not None: | ||
value = self.connections.get(port) | ||
if value is not None: | ||
return value | ||
return port | ||
|
||
|
||
class InputHandler(ABC): | ||
def __init__(self, *args, **kwargs): | ||
""" | ||
Handler interface for injecting external events to the system. | ||
:param queue: used to collect and inject all external events joining the system. | ||
:param Callable[[Any], tuple[str, str]] event_parser: event parser function. It transforms incoming events | ||
into tuples (port, message). Note that both are represented as strings. Messages need further parsing. | ||
:param dict[str, Callable[[str], Any]] msg_parsers: message parsers. Keys are port names, and values are | ||
functions that take a string and returns an object of the corresponding port type. If a parser is not | ||
defined, the input handler assumes that the port type is str and forward the message as is. By default, all | ||
the ports are assumed to accept str objects. | ||
""" | ||
self.queue = kwargs.get('queue') | ||
if self.queue is None: | ||
raise ValueError('queue is mandatory') | ||
self.event_parser: Callable[[Any], tuple[str, str]] | None = kwargs.get('event_parser') | ||
self.msg_parsers: dict[str, Callable[[str], Any]] = kwargs.get('msg_parsers', dict()) | ||
|
||
self.connections: dict[str, str] = kwargs.get('connections', dict()) | ||
self.connector = Connector(conections=self.connections) | ||
|
||
def initialize(self): | ||
"""Performs any task before calling the run method. It is implementation-specific. By default, it is empty.""" | ||
pass | ||
|
||
def exit(self): | ||
"""Performs any task after the run method. It is implementation-specific. By default, it is empty.""" | ||
pass | ||
|
||
@abstractmethod | ||
def run(self): | ||
"""Execution of the input handler. It is implementation-specific""" | ||
pass | ||
|
||
def push_event(self, event: Any): | ||
"""Parses event as tuple port-message and pushes it to the queue.""" | ||
try: | ||
port, msg = self.event_parser(event) | ||
# AQUI IRIA EL CONECTOR MQTT; para corregir el puerto en cuestion | ||
port = self.connector.input_handler(port) | ||
except Exception as e: | ||
# if an exception is triggered while parsing the event, we ignore it | ||
print(f'error parsing input event ("{event}"): {e}. Event will be ignored', file=sys.stderr) | ||
return | ||
self.push_msg(port, msg) | ||
|
||
def push_msg(self, port: str, msg: str): | ||
"""Parses the message as the proper object and pushes it to the queue.""" | ||
try: | ||
# if parser is not defined, we forward the message as is (i.e., in string format) | ||
msg = self.msg_parsers.get(port, lambda x: x)(msg) | ||
except Exception as e: | ||
# if an exception is triggered while parsing the message, we ignore it | ||
print(f'error parsing input msg ("{msg}") in port {port}: {e}. Message will be ignored', file=sys.stderr) | ||
return | ||
self.queue.put((port, msg)) | ||
|
||
|
||
class OutputHandler(ABC): | ||
def __init__(self, *args, **kwargs): | ||
""" | ||
Handler interface for ejecting internal events from the system. | ||
:param queue.SimpleQueue() queue: is the queue where all the desired events to be ejected are put. | ||
:param Callable[[str, str], Any] event_parser: event parser function. It transforms incoming tuples | ||
(port, message) into events. Note that both are represented as strings. | ||
:param dict[str, Callable[[Any], str]] msg_parser: message parsers. Keys are port names, and values are | ||
functions that take a string and returns an object of the corresponding port type. If a parser is not | ||
defined, the output handler assumes that the port type is str and forward the message as is. By default, all | ||
the ports are assumed to accept str objects. | ||
TODO documentation | ||
""" | ||
self.queue = queue.SimpleQueue() | ||
self.event_parser: Callable[[str, str], Any] | None = kwargs.get('event_parser') | ||
self.msg_parsers: dict[str, Callable[[Any], str]] = kwargs.get('msg_parsers', dict()) | ||
|
||
def initialize(self): | ||
"""Performs any task before calling the run method. It is implementation-specific. By default, it is empty.""" | ||
pass | ||
|
||
def exit(self): | ||
"""Performs any task before calling the run method. It is implementation-specific. By default, it is empty.""" | ||
pass | ||
|
||
@abstractmethod | ||
def run(self): | ||
"""Execution of the output handler. It is implementation-specific""" | ||
pass | ||
|
||
def pop_event(self) -> Any: | ||
"""Waits until it receives an outgoing event and parses it with the desired format.""" | ||
while True: | ||
port, msg = self.pop_msg() | ||
# print(f'POP_EVENT: recibo port = {port} y msg = {msg}') | ||
try: | ||
event = self.event_parser(port, msg) | ||
except Exception as e: | ||
print(f'error parsing output event ("{port}","{msg}"): {e}. Event will be ignored', file=sys.stderr) | ||
continue | ||
return event | ||
|
||
def pop_msg(self) -> tuple[str, str]: | ||
"""Waits until it receives an outgoing message and returns the port and message in string format.""" | ||
while True: | ||
port, msg = self.queue.get() | ||
# print(f'POP_MSG: recibo port = {port} y msg = {msg}') | ||
try: | ||
msg = self.msg_parsers.get(port, lambda x: str(x))(msg) | ||
except Exception as e: | ||
print(f'error parsing output msg ("{msg}"): {e}. Message will be ignored', file=sys.stderr) | ||
continue | ||
return port, msg |
Oops, something went wrong.