diff --git a/pyproject.toml b/pyproject.toml index b7f8cd6..26f306e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "thingtalk" -version = "0.7.13" +version = "0.7.14" description = "Web of Things framework, high performance, easy to learn, fast to code, ready for production" authors = ["hidaris "] readme = "README.md" @@ -40,6 +40,8 @@ mkdocs-material = { version = "^6.1.6", optional = true } async-cron = "^1.6.2" gmqtt = "^0.6.9" dynaconf = "^3.1.2" +click = "^7.1.2" +rich = "^9.10.0" [tool.poetry.dev-dependencies] pytest = "^6.0" @@ -49,3 +51,7 @@ black = {version = "^20.8b1", allow-prereleases = true} [tool.poetry.extras] docs = ["mkdocs-material"] + +[tool.poetry.scripts] +hello = 'thingtalk.app:hello' + diff --git a/thingtalk/__init__.py b/thingtalk/__init__.py index e9fdc02..e23457a 100644 --- a/thingtalk/__init__.py +++ b/thingtalk/__init__.py @@ -4,7 +4,7 @@ from .models.action import Action from .models.event import Event from .models.property import Property -from .app import app +from .app import app, hello from .models.containers import SingleThing, MultipleThings from .models.thing import Thing from .domains.iot import Device diff --git a/thingtalk/app.py b/thingtalk/app.py index 55ec6cc..8c5a0b1 100644 --- a/thingtalk/app.py +++ b/thingtalk/app.py @@ -1,4 +1,5 @@ import socket +import click from fastapi import FastAPI, APIRouter from loguru import logger @@ -21,8 +22,8 @@ description="Web of Things framework, high performance, easy to learn, fast to code, ready for production", ) server = Server() -server.href_prefix = f"/things/{server._id}" -app.state.things = MultipleThings({server._id: server}, "things") +server.href_prefix = f"/things/{server.id}" +app.state.things = MultipleThings({server.id: server}, "things") zeroconf = Zeroconf() @@ -106,3 +107,12 @@ async def publish(topic: str, payload: OutMsg): app.include_router(restapi) app.include_router(websockets.router) + + +@click.command() +@click.option("--count", default=1, e=int, help="Number of greetings.") +@click.option("--name", type=str, prompt="Your name", help="The person to greet.") +def hello(count: int, name: str): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") diff --git a/thingtalk/models/thing.py b/thingtalk/models/thing.py index 6ff9d59..a7d4d18 100644 --- a/thingtalk/models/thing.py +++ b/thingtalk/models/thing.py @@ -183,7 +183,7 @@ def href_prefix(self) -> str: return self._href_prefix @href_prefix.setter - def href_prefix(self, prefix: str): + def href_prefix(self, prefix: str) -> None: """ Set the prefix of any hrefs associated with this thing. prefix -- the prefix @@ -203,7 +203,7 @@ def ui_href(self) -> str: return self._ui_href @ui_href.setter - def ui_href(self, href): + def ui_href(self, href) -> None: """ Set the href of this thing's custom UI. href -- the href @@ -227,7 +227,7 @@ def title(self): return self._title @title.setter - def title(self, title): + def title(self, title) -> None: """ Set the new title of this thing. title -- the new title diff --git a/thingtalk/toolkits/mqtt.py b/thingtalk/toolkits/mqtt.py index 108d8d1..6f33975 100644 --- a/thingtalk/toolkits/mqtt.py +++ b/thingtalk/toolkits/mqtt.py @@ -73,6 +73,10 @@ def on_connect(self, client: Client, flags, rc, properties): async def on_message(self, client: Client, topic, payload, qos, properties): logger.info( f"[RECV MSG {client._client_id}] TOPIC: {topic} PAYLOAD: {payload} QOS: {qos} PROPERTIES: {properties}") + if topic == 'thingtalk/bridge/': + pass + if topic == 'thingtalk/+/config': + pass def on_disconnect(self, client: Client, packet, exc=None): logger.info(f"[DISCONNECTED {client._client_id}]") diff --git a/thingtalk/utils.py b/thingtalk/utils.py index 2d37422..9d5bc9a 100644 --- a/thingtalk/utils.py +++ b/thingtalk/utils.py @@ -6,6 +6,7 @@ import asyncio from contextlib import contextmanager +from loguru import logger from threading import Thread @@ -88,3 +89,52 @@ def run_forever(loop): finally: loop.call_soon_threadsafe(loop.stop) thread.join() + + +class PortDetect: + """ + 扫描本机的可用端口。 + eg: + pd = PortDetect() + pd() + print pd.avaliable + ==> + 50000 + + 默认会从本机的50000端口开始扫描,依次递增到55000,如果发现可用的端口则把端口号赋值给 + 类的成员变量avaliable,如果扫描完成后avaliable的值是0,说明所有端口都被占用了。 + + 也可以单独使用check_port方法,通过传入端口的方式来检查端口是否被占用。 + eg: + pd = PortDetect() + pd.check_port(9999) + + ==> + True + """ + def __init__(self, range_s=50000, range_e=55000): + self.range_s = range_s + self.range_e = range_e + self.available = 0 + + def check_port(self, port): + """ + 单独检查端口是否可用 + :param port: int, 端口号 + :return: Bool, True表示端口可用,False表示端口不可用 + """ + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + result = s.connect_ex(("127.0.0.1", int(port))) + if result == 0: + return False + else: + return True + + def __call__(self, *args, **kwargs): + for x in range(self.range_s, self.range_e): + rst = self.check_port(x) + if rst: + self.available = x + break + else: + logger.error("all port used")