Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:3.10-buster",
"image": "mcr.microsoft.com/devcontainers/python:3.12-bullseye",

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
Expand Down
208 changes: 104 additions & 104 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,105 +1,105 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.vscode
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ requires = ["setuptools>=42.0", "wheel"]
build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
asyncio_mode = "auto"
addopts = "--cov=velbustcp"
testpaths = [
"tests",
Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ packages = find_namespace:
install_requires =
pyserial==3.5
blinker==1.6.1
pyserial-asyncio-fast==0.14
python_requires = >=3.8
package_dir =
=src
Expand All @@ -25,6 +26,7 @@ testing =
pytest>=7.3.1
pytest-cov>=4.1.0
pytest-mock>=3.10.0
pytest-asyncio>=0.23.3
mypy>=1.3.0
flake8>=6.0.0
tox>=4.6.0
Expand Down
37 changes: 19 additions & 18 deletions src/velbustcp/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import argparse
import json
from threading import Event
import sys
import asyncio

from velbustcp.lib.connection.bridge import Bridge
from velbustcp.lib.connection.serial.bus import Bus
Expand Down Expand Up @@ -33,31 +33,24 @@ def __init__(self):
network_manager.add_network(network)

self.__bridge = Bridge(bus, network_manager)
self.__bridge.start()

def main_loop(self):
"""Main loop for the program, blocks infinitely until it receives a KeyboardInterrupt.
"""

q = Event()
q.wait()

def stop(self):
"""Stops bridge.
"""
async def start(self):
"""Starts the bridge."""
await self.__bridge.start()

self.__bridge.stop()
async def stop(self):
"""Stops the bridge."""
await self.__bridge.stop()


def main(args=None):
"""Main method."""
async def main_async(args=None):
"""Main asynchronous method."""
parser = argparse.ArgumentParser(description="Velbus communication")
parser.add_argument("--settings", help="Settings file", required=False)
args = parser.parse_args()

# If settings are supplied, read and validate them
if args.settings:

# Open settings file
with open(args.settings, 'r') as f:
settings = json.load(f)
Expand All @@ -72,7 +65,9 @@ def main(args=None):
main = Main()

try:
main.main_loop()
loop = asyncio.get_event_loop()
loop.run_until_complete(await main.start())
loop.run_forever()

except KeyboardInterrupt:
logger.info("Interrupted, shutting down")
Expand All @@ -81,10 +76,16 @@ def main(args=None):
logger.exception(e)

finally:
main.stop()
await main.stop()

logger.info("Shutdown")


# entrypoint for the snap
def main(args=None):
"""Main method."""
asyncio.run(main_async(args))


if __name__ == '__main__':
sys.exit(main())
21 changes: 12 additions & 9 deletions src/velbustcp/lib/connection/bridge.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from velbustcp.lib.connection.serial.bus import Bus
from velbustcp.lib.connection.tcp.networkmanager import NetworkManager
from velbustcp.lib.signals import on_bus_receive, on_bus_send, on_tcp_receive
import asyncio


class Bridge():
Expand All @@ -18,35 +19,37 @@ def __init__(self, bus: Bus, network_manager: NetworkManager):

def handle_bus_receive(sender, **kwargs):
packet = kwargs["packet"]
self.__network_manager.send(packet)
asyncio.create_task(self.__network_manager.send(packet))
self.handle_bus_receive = handle_bus_receive
on_bus_receive.connect(handle_bus_receive)

def handle_bus_send(sender, **kwargs):
packet = kwargs["packet"]
self.__network_manager.send(packet)
asyncio.create_task(self.__network_manager.send(packet))
self.handle_bus_send = handle_bus_send
on_bus_send.connect(handle_bus_send)

def handle_tcp_receive(sender, **kwargs):
packet = kwargs["packet"]
self.__bus.send(packet)
asyncio.create_task(self.__bus.send(packet))
self.handle_tcp_receive = handle_tcp_receive
on_tcp_receive.connect(handle_tcp_receive)

self.__bus: Bus = bus
self.__network_manager: NetworkManager = network_manager

def start(self) -> None:
async def start(self) -> None:
"""Starts bus and TCP network(s).
"""

self.__bus.ensure()
self.__network_manager.start()
serial_task = asyncio.create_task(self.__bus.ensure())
tcp_task = asyncio.create_task(self.__network_manager.start())

def stop(self) -> None:
await asyncio.gather(serial_task, tcp_task)

async def stop(self) -> None:
"""Stops NTP, bus and network.
"""

self.__bus.stop()
self.__network_manager.stop()
await self.__network_manager.stop()
await self.__bus.stop()
Loading