kopia lustrzana https://github.com/Yakifo/amqtt
commit
c3f3d0d3a2
|
@ -0,0 +1,37 @@
|
||||||
|
# Image name and tag
|
||||||
|
IMAGE_NAME := amqtt
|
||||||
|
IMAGE_TAG := latest
|
||||||
|
VERSION_TAG := 0.11.0
|
||||||
|
REGISTRY := amqtt/$(IMAGE_NAME)
|
||||||
|
|
||||||
|
# Platforms to build for
|
||||||
|
PLATFORMS := linux/amd64,linux/arm64
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
.PHONY: all
|
||||||
|
all: build
|
||||||
|
|
||||||
|
# Build multi-platform image
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
docker buildx build \
|
||||||
|
--platform $(PLATFORMS) \
|
||||||
|
--tag $(REGISTRY):$(IMAGE_TAG) \
|
||||||
|
--tag $(REGISTRY):$(VERSION_TAG) \
|
||||||
|
--file Dockerfile \
|
||||||
|
--push .
|
||||||
|
|
||||||
|
# Optional: build without pushing (for local testing)
|
||||||
|
.PHONY: build-local
|
||||||
|
build-local:
|
||||||
|
docker buildx build \
|
||||||
|
--tag $(REGISTRY):$(IMAGE_TAG) \
|
||||||
|
--tag $(REGISTRY):$(VERSION_TAG) \
|
||||||
|
--file Dockerfile \
|
||||||
|
--load .
|
||||||
|
|
||||||
|
# Create builder if not exists
|
||||||
|
.PHONY: init
|
||||||
|
init:
|
||||||
|
docker buildx create --use --name multi-builder || true
|
||||||
|
docker buildx inspect --bootstrap
|
|
@ -7,7 +7,7 @@
|
||||||

|

|
||||||
[](https://pypi.org/project/amqtt/)
|
[](https://pypi.org/project/amqtt/)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
`aMQTT` is an open source [MQTT](http://www.mqtt.org) broker and client[^1], natively implemented with Python's [asyncio](https://docs.python.org/3/library/asyncio.html).
|
`aMQTT` is an open source [MQTT](http://www.mqtt.org) broker and client[^1], natively implemented with Python's [asyncio](https://docs.python.org/3/library/asyncio.html).
|
||||||
|
|
||||||
|
|
192
docs/Makefile
192
docs/Makefile
|
@ -1,192 +0,0 @@
|
||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
PAPER =
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# User-friendly check for sphinx-build
|
|
||||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
|
||||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
# the i18n builder cannot share the environment and doctrees with the others
|
|
||||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "Please use \`make <target>' where <target> is one of"
|
|
||||||
@echo " html to make standalone HTML files"
|
|
||||||
@echo " dirhtml to make HTML files named index.html in directories"
|
|
||||||
@echo " singlehtml to make a single large HTML file"
|
|
||||||
@echo " pickle to make pickle files"
|
|
||||||
@echo " json to make JSON files"
|
|
||||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
|
||||||
@echo " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " applehelp to make an Apple Help Book"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp project"
|
|
||||||
@echo " epub to make an epub"
|
|
||||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
|
||||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
|
||||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
|
||||||
@echo " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " texinfo to make Texinfo files"
|
|
||||||
@echo " info to make Texinfo files and run them through makeinfo"
|
|
||||||
@echo " gettext to make PO message catalogs"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@echo " xml to make Docutils-native XML files"
|
|
||||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
|
||||||
@echo " linkcheck to check all external links for integrity"
|
|
||||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
|
||||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(BUILDDIR)/*
|
|
||||||
|
|
||||||
html:
|
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
|
||||||
|
|
||||||
dirhtml:
|
|
||||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
|
||||||
|
|
||||||
singlehtml:
|
|
||||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
|
||||||
|
|
||||||
pickle:
|
|
||||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the pickle files."
|
|
||||||
|
|
||||||
json:
|
|
||||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the JSON files."
|
|
||||||
|
|
||||||
htmlhelp:
|
|
||||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|
||||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/HBMQTT.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/HBMQTT.qhc"
|
|
||||||
|
|
||||||
applehelp:
|
|
||||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
|
||||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
|
||||||
"~/Library/Documentation/Help or install it in your application" \
|
|
||||||
"bundle."
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/HBMQTT"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/HBMQTT"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
epub:
|
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
|
||||||
|
|
||||||
latex:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
|
||||||
|
|
||||||
latexpdf:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo "Running LaTeX files through pdflatex..."
|
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
|
||||||
|
|
||||||
latexpdfja:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
|
||||||
|
|
||||||
text:
|
|
||||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
|
||||||
|
|
||||||
man:
|
|
||||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
|
||||||
|
|
||||||
texinfo:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
|
||||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
|
||||||
"(use \`make info' here to do that automatically)."
|
|
||||||
|
|
||||||
info:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo "Running Texinfo files through makeinfo..."
|
|
||||||
make -C $(BUILDDIR)/texinfo info
|
|
||||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
|
||||||
|
|
||||||
gettext:
|
|
||||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
|
||||||
|
|
||||||
changes:
|
|
||||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
|
||||||
@echo
|
|
||||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
|
||||||
|
|
||||||
linkcheck:
|
|
||||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
|
||||||
@echo
|
|
||||||
@echo "Link check complete; look for any errors in the above output " \
|
|
||||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
|
||||||
|
|
||||||
doctest:
|
|
||||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
|
||||||
@echo "Testing of doctests in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/doctest/output.txt."
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
|
||||||
@echo "Testing of coverage in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/coverage/python.txt."
|
|
||||||
|
|
||||||
xml:
|
|
||||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
|
||||||
|
|
||||||
pseudoxml:
|
|
||||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
|
|
@ -2,13 +2,42 @@
|
||||||
|
|
||||||
## 0.11.0
|
## 0.11.0
|
||||||
|
|
||||||
- Removed hbmqtt compatibility, importing amqtt is now mandatory
|
- upgrades to support python 3.10, 3.11, 3.12 and 3.13
|
||||||
- Removed loop parameter from all functions
|
- complete type hinting of the entire codebase
|
||||||
- Python 3.10 to 3.13 compatibility
|
- linting with ruff, pylint and mypy to keep the codebase consistent in format and structure
|
||||||
- Fixed a major bug in plugin api, see [PR #92](https://github.com/Yakifo/amqtt/pull/92)
|
- github workflow CI of linting before pull requests can be merged
|
||||||
- Migrated from `docopts` to `typer`
|
- run linting with git pre-commit hooks
|
||||||
|
- add docker container
|
||||||
|
- switch to discord
|
||||||
|
- updates to community contribution guidance, code of conduct, etc.
|
||||||
|
- overhaul of the documentation, including move to mkdocs with the materials UI
|
||||||
|
- updated plugin documentation and full docs for the broker/client configuration
|
||||||
|
- updated doc strings and cli help messages, including auto generation of those aspects into the docs
|
||||||
|
- [Issue #215](https://github.com/Yakifo/amqtt/issues/215) test_sys.py fails on github, but not locally
|
||||||
|
- [Issue #210](https://github.com/Yakifo/amqtt/issues/210) NoDataError thrown instead of ConnectError when client fails authentication
|
||||||
|
- [Issue #199](https://github.com/Yakifo/amqtt/issues/199) will message being sent even if client properly disconnects
|
||||||
|
- [Issue #180](https://github.com/Yakifo/amqtt/issues/180) plugin broker sys: incorrect uptime topic
|
||||||
|
- [Issue #178](https://github.com/Yakifo/amqtt/issues/178) consolidate broker configuration documentation
|
||||||
|
- [Issue #170](https://github.com/Yakifo/amqtt/issues/170) compatibility test cases: paho-mqtt
|
||||||
|
- [Issue #159](https://github.com/Yakifo/amqtt/issues/159) Client last will (LWT) example and documentation
|
||||||
|
- [Issue #157](https://github.com/Yakifo/amqtt/issues/157) loop = asyncio.get_event_loop() is deprecated
|
||||||
|
- [Issue #154](https://github.com/Yakifo/amqtt/issues/154) broker rejects connect with empty will message
|
||||||
|
- [Issue #144](https://github.com/Yakifo/amqtt/issues/144) Allow amqtt.client.MQTTClient to always reconnect via config
|
||||||
|
- [Issue #105](https://github.com/Yakifo/amqtt/issues/105) Add stack traces to logging
|
||||||
|
- [Issue #95](https://github.com/Yakifo/amqtt/issues/95) asyncio.get_event_loop() deprecated in Python 3.10
|
||||||
|
- [Issue #94](https://github.com/Yakifo/amqtt/issues/94) test matrix for dependencies
|
||||||
|
- [Issue #70](https://github.com/Yakifo/amqtt/issues/70) event and plugin documentation
|
||||||
|
- [Issue #67](https://github.com/Yakifo/amqtt/issues/67) MQTTClient fails to raise appropriate exception if URI is broken
|
||||||
|
- [Issue #51](https://github.com/Yakifo/amqtt/issues/51) failing plugin kills the broker
|
||||||
|
- [Issue #48](https://github.com/Yakifo/amqtt/issues/48) Setup unit tests running against different versions of dependencies
|
||||||
|
- [Issue #35](https://github.com/Yakifo/amqtt/issues/35) plugin interface and optimization
|
||||||
|
|
||||||
## 0.10.0
|
|
||||||
|
## 0.10.2
|
||||||
|
|
||||||
|
- create the necessary .readthedocs.yaml to generate sphinx docs from the 0.10.x series
|
||||||
|
|
||||||
|
## 0.10.1
|
||||||
|
|
||||||
- First release under new package name: amqtt
|
- First release under new package name: amqtt
|
||||||
- Reworked unit tests
|
- Reworked unit tests
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Containerization
|
# Containerization
|
||||||
|
|
||||||
Built from [dockerfile](https://github.com/Yakifo/amqtt/blob/main/dockerfile), the default `aMQTT` broker is publicly available on [DockerHub](https://hub.docker.com/repository/docker/amqtt/amqtt).
|
`amqtt` library is available on [PyPI](https://pypi.python.org/pypi/amqtt), [GitHub](https://github.com/Yakifo/amqtt) and [Read the Docs](http://amqtt.readthedocs.org/).
|
||||||
|
|
||||||
|
Built from [Dockerfile](https://github.com/Yakifo/amqtt/blob/main/dockerfile), the default `aMQTT` broker is publicly available on [DockerHub](https://hub.docker.com/repository/docker/amqtt/amqtt).
|
||||||
|
|
||||||
## Launch
|
## Launch
|
||||||
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
HBMQTT Transition
|
|
||||||
==================================
|
|
||||||
|
|
||||||
This document is for those porting from HBMQTT to aMQTT.
|
|
||||||
Basically you can search and replace ``hbmqtt`` with ``amqtt`` and all should work out.
|
|
||||||
Details below.
|
|
||||||
|
|
||||||
|
|
||||||
Imports
|
|
||||||
-------
|
|
||||||
|
|
||||||
The module changed from ``hbmqtt`` to ``amqtt``.
|
|
||||||
For the 0.10.x releases it will still be possible to ``import hbmqtt``.
|
|
||||||
In 0.11.x only ``amqtt`` will work.
|
|
||||||
|
|
||||||
Since the ``amqtt`` package does provide a ``hbmqtt`` module, installing the ``hbmqtt`` package in the same python installation is not possible.
|
|
||||||
|
|
||||||
|
|
||||||
Random Client ID
|
|
||||||
----------------
|
|
||||||
|
|
||||||
When not providing a client_id, a random id is automatically generated.
|
|
||||||
These names were also changed from ``hbmqtt/<random>`` to ``amqtt/<random>``.
|
|
||||||
|
|
||||||
plugins / entrypoints
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
If you make use of python's entrypoint system to build aMQTT plugins, make sure to use the ``amqtt.*.plugins`` names instead of ``hbmqtt.*.plugins`` names.
|
|
||||||
During the transition plugins with ``hbmqtt`` entrypoint should keep working for 0.10.x releases.
|
|
||||||
|
|
||||||
|
|
||||||
CLI tools
|
|
||||||
---------
|
|
||||||
|
|
||||||
* Renamed `hbmqtt` to `amqtt`
|
|
||||||
* Renamed `hbmqtt_pub` to `amqtt_pub`
|
|
||||||
* Renamed `hbmqtt_sub` to `amqtt_pub`
|
|
|
@ -1,2 +1,3 @@
|
||||||
|
VITE_MQTT_WS_TYPE = ws
|
||||||
VITE_MQTT_WS_HOST = not_set
|
VITE_MQTT_WS_HOST = not_set
|
||||||
VITE_MQTT_WS_PORT = 9999
|
VITE_MQTT_WS_PORT = 9999
|
|
@ -1,2 +1,3 @@
|
||||||
|
VITE_MQTT_WS_TYPE = ws
|
||||||
VITE_MQTT_WS_HOST = localhost
|
VITE_MQTT_WS_HOST = localhost
|
||||||
VITE_MQTT_WS_PORT = 8080
|
VITE_MQTT_WS_PORT = 8080
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
|
VITE_MQTT_WS_TYPE = wss
|
||||||
VITE_MQTT_WS_HOST = test.amqtt.io
|
VITE_MQTT_WS_HOST = test.amqtt.io
|
||||||
VITE_MQTT_WS_PORT = 8080
|
VITE_MQTT_WS_PORT = 8443
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "amqttio",
|
"name": "amqttio",
|
||||||
"version": "0.0.0",
|
"version": "0.11.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "amqttio",
|
"name": "amqttio",
|
||||||
"version": "0.0.0",
|
"version": "0.11.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "amqttio",
|
"name": "amqttio",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.11.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build --mode production",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,11 +5,12 @@ import Typography from '@mui/material/Typography';
|
||||||
import Copyright from '../internals/components/Copyright';
|
import Copyright from '../internals/components/Copyright';
|
||||||
import SessionsChart from './SessionsChart';
|
import SessionsChart from './SessionsChart';
|
||||||
import {useEffect, useState} from "react";
|
import {useEffect, useState} from "react";
|
||||||
import useMqtt from '../../assets/usemqtt';
|
// @ts-ignore
|
||||||
import type { DataPoint } from '../../assets/helpers';
|
import useMqtt from '../../assets/usemqtt';
|
||||||
|
import type {DataPoint} from '../../assets/helpers';
|
||||||
import {Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@mui/material";
|
import {Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow} from "@mui/material";
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
|
||||||
import { faGithub, faPython, faDocker, faDiscord } from "@fortawesome/free-brands-svg-icons";
|
import {faGithub, faPython, faDocker, faDiscord} from "@fortawesome/free-brands-svg-icons";
|
||||||
|
|
||||||
import rtdIcon from "../../assets/readthedocs.svg";
|
import rtdIcon from "../../assets/readthedocs.svg";
|
||||||
|
|
||||||
|
@ -22,35 +23,36 @@ export default function MainGrid() {
|
||||||
const [serverStart, setServerStart] = useState<string>('');
|
const [serverStart, setServerStart] = useState<string>('');
|
||||||
const [serverUptime, setServerUptime] = useState<string>('');
|
const [serverUptime, setServerUptime] = useState<string>('');
|
||||||
|
|
||||||
function getRandomInt(min:number, max:number) {
|
function getRandomInt(min: number, max: number) {
|
||||||
min = Math.ceil(min);
|
min = Math.ceil(min);
|
||||||
max = Math.floor(max);
|
max = Math.floor(max);
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
function secondsToDhms(seconds: int) {
|
function secondsToDhms(seconds: number) {
|
||||||
const days = Math.floor(seconds / (24 * 3600));
|
const days = Math.floor(seconds / (24 * 3600));
|
||||||
seconds %= (24 * 3600);
|
seconds %= (24 * 3600);
|
||||||
const hours = Math.floor(seconds / 3600);
|
const hours = Math.floor(seconds / 3600);
|
||||||
seconds %= 3600;
|
seconds %= 3600;
|
||||||
const minutes = Math.floor(seconds / 60);
|
const minutes = Math.floor(seconds / 60);
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
|
|
||||||
return {
|
|
||||||
days: days,
|
|
||||||
hours: hours,
|
|
||||||
minutes: minutes,
|
|
||||||
seconds: seconds,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
days: days,
|
||||||
|
hours: hours,
|
||||||
|
minutes: minutes,
|
||||||
|
seconds: seconds,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const mqtt_settings = {
|
const mqtt_settings = {
|
||||||
url: 'ws://' + import.meta.env.VITE_MQTT_WS_HOST,
|
url: import.meta.env.VITE_MQTT_WS_TYPE + '://' + import.meta.env.VITE_MQTT_WS_HOST + ':' + import.meta.env.VITE_MQTT_WS_PORT, client_id: `web-client-${getRandomInt(1, 100)}`,
|
||||||
client_id: `web-client-${getRandomInt(1, 100)}`,
|
clean: true,
|
||||||
config: {
|
protocol: 'wss',
|
||||||
port: import.meta.env.VITE_MQTT_WS_PORT
|
protocolVersion: 4, // MQTT 3.1.1
|
||||||
}
|
wsOptions: {
|
||||||
|
protocol: 'mqtt'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const {mqttSubscribe, isConnected, messageQueue, messageTick} = useMqtt(mqtt_settings);
|
const {mqttSubscribe, isConnected, messageQueue, messageTick} = useMqtt(mqtt_settings);
|
||||||
|
@ -68,7 +70,7 @@ function secondsToDhms(seconds: int) {
|
||||||
|
|
||||||
while (messageQueue.current.length > 0) {
|
while (messageQueue.current.length > 0) {
|
||||||
const payload = messageQueue.current.shift()!;
|
const payload = messageQueue.current.shift()!;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const d = payload.message;
|
const d = payload.message;
|
||||||
if (payload.topic === '$SYS/broker/messages/publish/sent') {
|
if (payload.topic === '$SYS/broker/messages/publish/sent') {
|
||||||
|
@ -99,28 +101,27 @@ function secondsToDhms(seconds: int) {
|
||||||
const dt = new Date(d + "Z");
|
const dt = new Date(d + "Z");
|
||||||
setServerStart(dt.toLocaleString());
|
setServerStart(dt.toLocaleString());
|
||||||
} else if (payload.topic === '$SYS/broker/uptime') {
|
} else if (payload.topic === '$SYS/broker/uptime') {
|
||||||
const { days, hours, minutes, seconds } = secondsToDhms(d);
|
const {days, hours, minutes, seconds} = secondsToDhms(d);
|
||||||
setServerUptime(`${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`);
|
setServerUptime(`${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`);
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [messageTick, messageQueue]);
|
}, [messageTick, messageQueue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ width: '100%', maxWidth: { sm: '100%', md: '1700px' } }}>
|
<Box sx={{width: '100%', maxWidth: {sm: '100%', md: '1700px'}}}>
|
||||||
{/* cards */}
|
{/* cards */}
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
spacing={2}
|
spacing={2}
|
||||||
columns={12}
|
columns={12}
|
||||||
sx={{ mb: (theme) => theme.spacing(2) }}
|
sx={{mb: (theme) => theme.spacing(2)}}
|
||||||
>
|
>
|
||||||
<Grid size={{ xs: 10, md: 5 }}>
|
<Grid size={{xs: 10, md: 5}}>
|
||||||
<Typography component="h2" variant="h6" sx={{ mb: 2 }}>
|
<Typography component="h2" variant="h6" sx={{mb: 2}}>
|
||||||
Overview
|
Overview
|
||||||
</Typography>
|
</Typography>
|
||||||
<div>
|
<div>
|
||||||
|
@ -134,15 +135,18 @@ function secondsToDhms(seconds: int) {
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style={{width:250}}>
|
<td style={{width: 250}}>
|
||||||
<p style={{textAlign: 'left'}}>
|
<p style={{textAlign: 'left'}}>
|
||||||
<FontAwesomeIcon icon={faGithub} size="xl"/> github: <a href="https://github.com/Yakofo/amqtt">Yakifo/amqtt</a>
|
<FontAwesomeIcon icon={faGithub} size="xl"/> github: <a
|
||||||
|
href="https://github.com/Yakofo/amqtt">Yakifo/amqtt</a>
|
||||||
</p>
|
</p>
|
||||||
<p style={{textAlign: 'left'}}>
|
<p style={{textAlign: 'left'}}>
|
||||||
<FontAwesomeIcon icon={faPython} size="xl"/> PyPi: <a href="https://pypi.org/project/amqtt/">aMQTT</a>
|
<FontAwesomeIcon icon={faPython} size="xl"/> PyPi: <a
|
||||||
|
href="https://pypi.org/project/amqtt/">aMQTT</a>
|
||||||
</p>
|
</p>
|
||||||
<p style={{textAlign: 'left'}}>
|
<p style={{textAlign: 'left'}}>
|
||||||
<FontAwesomeIcon icon={faDiscord} size="xl"/> Discord: <a href="https://discord.gg/S3sP6dDaF3">aMQTT</a>
|
<FontAwesomeIcon icon={faDiscord} size="xl"/> Discord: <a
|
||||||
|
href="https://discord.gg/S3sP6dDaF3">aMQTT</a>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -155,9 +159,10 @@ function secondsToDhms(seconds: int) {
|
||||||
ReadTheDocs: <a href="https://amqtt.readthedocs.io/">aMQTT</a>
|
ReadTheDocs: <a href="https://amqtt.readthedocs.io/">aMQTT</a>
|
||||||
</p>
|
</p>
|
||||||
<p style={{textAlign: 'left'}}>
|
<p style={{textAlign: 'left'}}>
|
||||||
<FontAwesomeIcon icon={faDocker} size="xl"/> DockerHub: <a href="https://hub.docker.com/repositories/amqtt">aMQTT</a>
|
<FontAwesomeIcon icon={faDocker} size="xl"/> DockerHub: <a
|
||||||
|
href="https://hub.docker.com/repositories/amqtt">aMQTT</a>
|
||||||
</p>
|
</p>
|
||||||
<p> </p>
|
<p> </p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -218,8 +223,8 @@ function secondsToDhms(seconds: int) {
|
||||||
|
|
||||||
|
|
||||||
<strong>broker started at </strong> {serverStart}
|
<strong>broker started at </strong> {serverStart}
|
||||||
<strong>up for</strong> {serverUptime}
|
<strong>up for</strong> {serverUptime}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid size={{xs: 12, md: 6}}>
|
<Grid size={{xs: 12, md: 6}}>
|
||||||
<SessionsChart title={'Sent Messages'} label={'Messages'} data={sent} isConnected={isConnected}/>
|
<SessionsChart title={'Sent Messages'} label={'Messages'} data={sent} isConnected={isConnected}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -229,18 +234,18 @@ function secondsToDhms(seconds: int) {
|
||||||
<Grid size={{xs: 12, md: 6}}>
|
<Grid size={{xs: 12, md: 6}}>
|
||||||
<SessionsChart title={'Bytes Out'} label={'Bytes'} data={bytesOut} isConnected={isConnected}/>
|
<SessionsChart title={'Bytes Out'} label={'Bytes'} data={bytesOut} isConnected={isConnected}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid size={{ xs: 12, md: 6 }}>
|
<Grid size={{xs: 12, md: 6}}>
|
||||||
<SessionsChart title={'Bytes In'} label={'Bytes'} data={bytesIn} isConnected={isConnected} />
|
<SessionsChart title={'Bytes In'} label={'Bytes'} data={bytesIn} isConnected={isConnected}/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid container spacing={2} columns={12}>
|
<Grid container spacing={2} columns={12}>
|
||||||
<Grid size={{ xs: 12, lg: 9 }}></Grid>
|
<Grid size={{xs: 12, lg: 9}}></Grid>
|
||||||
<Grid size={{ xs: 12, lg: 3 }}>
|
<Grid size={{xs: 12, lg: 3}}>
|
||||||
<Stack gap={2} direction={{ xs: 'column', sm: 'row', lg: 'column' }}></Stack>
|
<Stack gap={2} direction={{xs: 'column', sm: 'row', lg: 'column'}}></Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Copyright sx={{ my: 4 }} />
|
<Copyright sx={{my: 4}}/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import Stack from '@mui/material/Stack';
|
||||||
import { LineChart } from '@mui/x-charts/LineChart';
|
import { LineChart } from '@mui/x-charts/LineChart';
|
||||||
import CountUp from 'react-countup';
|
import CountUp from 'react-countup';
|
||||||
import type { DataPoint } from '../../assets/helpers.jsx';
|
import type { DataPoint } from '../../assets/helpers.jsx';
|
||||||
import React from "react";
|
|
||||||
import {CircularProgress} from "@mui/material";
|
import {CircularProgress} from "@mui/material";
|
||||||
|
|
||||||
const currentTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
const currentTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
|
|
@ -11,7 +11,7 @@ listeners:
|
||||||
bind: 0.0.0.0:8883
|
bind: 0.0.0.0:8883
|
||||||
ssl: on
|
ssl: on
|
||||||
certfile: /etc/letsencrypt/live/test.amqtt.io/fullchain.pem
|
certfile: /etc/letsencrypt/live/test.amqtt.io/fullchain.pem
|
||||||
keyfile: /etc/letsencrypt/live/test.amqtt.io/privkey.pemkk
|
keyfile: /etc/letsencrypt/live/test.amqtt.io/privkey.pem
|
||||||
tls-ws:
|
tls-ws:
|
||||||
type: ws
|
type: ws
|
||||||
bind: 0.0.0.0:8443
|
bind: 0.0.0.0:8443
|
||||||
|
|
|
@ -5,7 +5,7 @@ site_description: "Python's asyncio-native MQTT broker and client."
|
||||||
site_url: http://github.com
|
site_url: http://github.com
|
||||||
repo_url: https://github.com/Yakifo/amqtt
|
repo_url: https://github.com/Yakifo/amqtt
|
||||||
repo_name: Yakifo/amqtt
|
repo_name: Yakifo/amqtt
|
||||||
site_dir: "site"
|
site_dir: "dist/rtd"
|
||||||
watch:
|
watch:
|
||||||
- mkdocs.rtd.yml
|
- mkdocs.rtd.yml
|
||||||
- README.md
|
- README.md
|
||||||
|
|
|
@ -3,7 +3,7 @@ site_description: "MQTT broker and client natively implemented with Python's asy
|
||||||
site_url: http://github.com
|
site_url: http://github.com
|
||||||
repo_url: https://github.com/Yakifo/amqtt
|
repo_url: https://github.com/Yakifo/amqtt
|
||||||
repo_name: Yakifo/amqtt
|
repo_name: Yakifo/amqtt
|
||||||
site_dir: "site_web"
|
site_dir: "dist/web"
|
||||||
docs_dir: docs_web
|
docs_dir: docs_web
|
||||||
watch: [mkdocs.web.yml, docs_web]
|
watch: [mkdocs.web.yml, docs_web]
|
||||||
copyright: "amqtt.io © 2025"
|
copyright: "amqtt.io © 2025"
|
||||||
|
|
|
@ -20,7 +20,7 @@ classifiers = [
|
||||||
"Programming Language :: Python :: 3.13"
|
"Programming Language :: Python :: 3.13"
|
||||||
]
|
]
|
||||||
|
|
||||||
version = "0.11.0rc1"
|
version = "0.11.0"
|
||||||
requires-python = ">=3.10.0"
|
requires-python = ">=3.10.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { text = "MIT" }
|
license = { text = "MIT" }
|
||||||
|
@ -33,7 +33,6 @@ dependencies = [
|
||||||
"passlib==1.7.4", # https://pypi.org/project/passlib
|
"passlib==1.7.4", # https://pypi.org/project/passlib
|
||||||
"PyYAML==6.0.2", # https://pypi.org/project/PyYAML
|
"PyYAML==6.0.2", # https://pypi.org/project/PyYAML
|
||||||
"typer==0.15.4",
|
"typer==0.15.4",
|
||||||
"dacite>=1.9.2",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
@ -88,15 +87,13 @@ amqtt_pub = "amqtt.scripts.pub_script:main"
|
||||||
amqtt_sub = "amqtt.scripts.sub_script:main"
|
amqtt_sub = "amqtt.scripts.sub_script:main"
|
||||||
|
|
||||||
[tool.hatch.build.targets.sdist]
|
[tool.hatch.build.targets.sdist]
|
||||||
include = ["/amqtt"]
|
include = ["/amqtt", "README.md"]
|
||||||
|
|
||||||
[tool.hatch.version]
|
[tool.hatch.version]
|
||||||
source = "vcs"
|
source = "vcs"
|
||||||
|
|
||||||
[tool.poe.tasks]
|
[tool.hatch.publish.indexes.testpypi]
|
||||||
rtd = "mkdocs serve -f mkdocs.rtd.yml"
|
url = "https://test.pypi.org/legacy/"
|
||||||
test = "pytest"
|
|
||||||
docs = "mkdocs build"
|
|
||||||
|
|
||||||
# ___________________________________ PLUGINS __________________________________
|
# ___________________________________ PLUGINS __________________________________
|
||||||
[project.entry-points."amqtt.test.plugins"]
|
[project.entry-points."amqtt.test.plugins"]
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
services:
|
services:
|
||||||
amqtt:
|
amqtt:
|
||||||
image: amqtt
|
image: amqtt/amqtt
|
||||||
container_name: amqtt
|
container_name: amqtt
|
||||||
ports:
|
ports:
|
||||||
- "1883:1883"
|
- "1883:1883"
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
- "8443:8443"
|
||||||
|
- "8883:8883"
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
|
@ -12,3 +14,4 @@ services:
|
||||||
max-file: "3"
|
max-file: "3"
|
||||||
volumes:
|
volumes:
|
||||||
- ./broker.yaml:/app/conf/broker.yaml
|
- ./broker.yaml:/app/conf/broker.yaml
|
||||||
|
- /etc/letsencrypt:/app/cert:ro
|
||||||
|
|
13
uv.lock
13
uv.lock
|
@ -9,10 +9,9 @@ resolution-markers = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "amqtt"
|
name = "amqtt"
|
||||||
version = "0.11.0rc1"
|
version = "0.11.0"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "dacite" },
|
|
||||||
{ name = "passlib" },
|
{ name = "passlib" },
|
||||||
{ name = "pyyaml" },
|
{ name = "pyyaml" },
|
||||||
{ name = "transitions" },
|
{ name = "transitions" },
|
||||||
|
@ -67,7 +66,6 @@ docs = [
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "coveralls", marker = "extra == 'ci'", specifier = "==4.0.1" },
|
{ name = "coveralls", marker = "extra == 'ci'", specifier = "==4.0.1" },
|
||||||
{ name = "dacite", specifier = ">=1.9.2" },
|
|
||||||
{ name = "passlib", specifier = "==1.7.4" },
|
{ name = "passlib", specifier = "==1.7.4" },
|
||||||
{ name = "pyyaml", specifier = "==6.0.2" },
|
{ name = "pyyaml", specifier = "==6.0.2" },
|
||||||
{ name = "transitions", specifier = "==0.9.2" },
|
{ name = "transitions", specifier = "==0.9.2" },
|
||||||
|
@ -487,15 +485,6 @@ version = "0.9.5"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/2a/8c3ac3d8bc94e6de8d7ae270bb5bc437b210bb9d6d9e46630c98f4abd20c/csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05", size = 237808, upload-time = "2017-11-26T21:13:08.238Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/f1/2a/8c3ac3d8bc94e6de8d7ae270bb5bc437b210bb9d6d9e46630c98f4abd20c/csscompressor-0.9.5.tar.gz", hash = "sha256:afa22badbcf3120a4f392e4d22f9fff485c044a1feda4a950ecc5eba9dd31a05", size = 237808, upload-time = "2017-11-26T21:13:08.238Z" }
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dacite"
|
|
||||||
version = "1.9.2"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/55/a0/7ca79796e799a3e782045d29bf052b5cde7439a2bbb17f15ff44f7aacc63/dacite-1.9.2.tar.gz", hash = "sha256:6ccc3b299727c7aa17582f0021f6ae14d5de47c7227932c47fec4cdfefd26f09", size = 22420, upload-time = "2025-02-05T09:27:29.757Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/35/386550fd60316d1e37eccdda609b074113298f23cef5bddb2049823fe666/dacite-1.9.2-py3-none-any.whl", hash = "sha256:053f7c3f5128ca2e9aceb66892b1a3c8936d02c686e707bee96e19deef4bc4a0", size = 16600, upload-time = "2025-02-05T09:27:24.345Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dill"
|
name = "dill"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
Ładowanie…
Reference in New Issue