diff --git a/service.py b/service.py
index bf25fd4..40e7476 100644
--- a/service.py
+++ b/service.py
@@ -11,7 +11,7 @@ from logger import logger
#mesh
from mesht_device import MeshtDevice
-from mesht_models import _wait_for_config_complete
+from mesht_models import _wait_for_config_complete, PUB_CH
from mesht_models import NOT_CONNECTED, WAIT_CONFIG, AVAILABLE, ERR, RECONNECT
#fs imports
@@ -41,6 +41,7 @@ class MeshListener(MeshArgsParse):
def __init__(self, args):
super().__init__(args)
self.meshState = NOT_CONNECTED
+ self.PUB_CH = PUB_CH
if args.transport == "serial":
from transport_serial import SerialTransport
@@ -231,7 +232,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser()
#mesh
parser.add_argument("--transport", default="ble")
- parser.add_argument("--disable-mesh", action="store_true", default=False)
+ parser.add_argument("--disable-mesh", action="store_true", default=True)
#serial transport
parser.add_argument("--serial-port", default="/dev/tty.usbmodemD0CF1309DC141")
parser.add_argument("--serial-baudrate", default=115200)
diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html
index 2a0fbf1..ffee8d5 100644
--- a/ui/src/app/app.component.html
+++ b/ui/src/app/app.component.html
@@ -1,484 +1,20 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ title }} app is running!
-
-
-
-
-
-
-
Resources
-
Here are some links to help you get started:
-
-
-
-
- Learn Angular
-
-
-
-
- CLI Documentation
-
-
-
-
-
- Angular Material
-
-
-
-
-
- Angular Blog
-
-
-
-
-
- Angular DevTools
-
-
-
+
+
+ MeshCenter
+
+ Имя ноды чела который авторизовался (мб еще snnr rxxi шуе)
+
+
+
+
+
+
+
+
-
- Next Steps
- What do you want to do next with your app?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
ng generate component xyz
-
ng add @angular/material
-
ng add @angular/pwa
-
ng add _____
-
ng test
-
ng build
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/ui/src/app/app.component.scss b/ui/src/app/app.component.scss
index e69de29..cbdde49 100644
--- a/ui/src/app/app.component.scss
+++ b/ui/src/app/app.component.scss
@@ -0,0 +1,19 @@
+.container {
+ width: 100%;
+ height: 100% - 2.5%;
+}
+
+.sidenav-content {
+ display: flex;
+ //height: 100%;
+ align-items: center;
+ justify-content: center;
+}
+
+.sidenav {
+ padding: 20px;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts
index e223dac..0741c53 100644
--- a/ui/src/app/app.component.ts
+++ b/ui/src/app/app.component.ts
@@ -6,5 +6,10 @@ import { Component } from '@angular/core';
styleUrls: ['./app.component.scss']
})
export class AppComponent {
- title = 'ui';
+ routes: {name: string, url: string}[] = [
+ {name: "Команды бота", url:""},
+ {name: "История сообщений", url:""},
+ {name: "Статистика по нодам", url:""},
+ {name: "Связь", url:""},
+ ]
}
diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts
index 5c20967..81f9a69 100644
--- a/ui/src/app/app.module.ts
+++ b/ui/src/app/app.module.ts
@@ -4,6 +4,11 @@ import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import {MatToolbarModule} from "@angular/material/toolbar";
+import {MatIconModule} from "@angular/material/icon";
+import {MatSidenavModule} from "@angular/material/sidenav";
+import {MatButtonModule} from "@angular/material/button";
+import {HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
@@ -12,7 +17,12 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
imports: [
BrowserModule,
AppRoutingModule,
- BrowserAnimationsModule
+ BrowserAnimationsModule,
+ MatToolbarModule,
+ MatIconModule,
+ MatSidenavModule,
+ MatButtonModule,
+ HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
diff --git a/webExtensions/extra/MessageDTO.py b/webExtensions/extra/MessageDTO.py
new file mode 100644
index 0000000..f3e8b74
--- /dev/null
+++ b/webExtensions/extra/MessageDTO.py
@@ -0,0 +1,6 @@
+__slots__ = ["from", "to", "rx_snr", "hop_limit", "rx_rssi", "hop_start", "ts", "decoded_payload", "want_ack"]
+
+class MessageDTO:
+ def __init__(self, data):
+ for slot in __slots__:
+ setattr(self, slot, data.get(slot, None))
\ No newline at end of file
diff --git a/webExtensions/extra/NodeDTO.py b/webExtensions/extra/NodeDTO.py
new file mode 100644
index 0000000..8e490ce
--- /dev/null
+++ b/webExtensions/extra/NodeDTO.py
@@ -0,0 +1,6 @@
+__slots__ = ["num", "snr", "hops_away", "ts", "long_name", "short_name"]
+
+class NodeDTO:
+ def __init__(self, data):
+ for slot in __slots__:
+ setattr(self, slot, data.get(slot, None))
\ No newline at end of file
diff --git a/webExtensions/messageList.py b/webExtensions/messageList.py
new file mode 100644
index 0000000..99290f5
--- /dev/null
+++ b/webExtensions/messageList.py
@@ -0,0 +1,24 @@
+from fastapi import FastAPI
+from fastapi.responses import HTMLResponse
+from fastapi import Query
+
+from pymongo.asynchronous.database import AsyncDatabase
+from extra.MessageDTO import MessageDTO
+from typing import List, Annotated
+from pymongo import DESCENDING
+
+class WebExtension:
+ MESSAGE_PORTNUM = 1
+ app: FastAPI
+ dbStore: AsyncDatabase
+ def __init__(self, core):
+ self.core = core
+ self.app = core.app
+ self.dbStore = core.dbStore
+
+ @self.app.get(f"{self.core.context}/messages")
+ async def listOfMessages(limit: int = Query(10), offset: int = Query(0)):
+ collection = self.dbStore['packet']
+ c = collection.find({"to": int(self.core.PUB_CH), "portnum":self.MESSAGE_PORTNUM}).sort("ts", DESCENDING).skip(offset).limit(limit)
+ l = await c.to_list()
+ return [MessageDTO(msg) for msg in l]
\ No newline at end of file
diff --git a/webExtensions/nodeList.py b/webExtensions/nodeList.py
new file mode 100644
index 0000000..12211d5
--- /dev/null
+++ b/webExtensions/nodeList.py
@@ -0,0 +1,89 @@
+from fastapi import FastAPI
+from fastapi.responses import HTMLResponse
+from fastapi import Query
+
+from pymongo.asynchronous.database import AsyncDatabase
+from extra.NodeDTO import NodeDTO
+from typing import List, Annotated
+
+class WebExtension:
+ app: FastAPI
+ dbStore: AsyncDatabase
+ def __init__(self, core):
+ self.core = core
+ self.app = core.app
+ self.dbStore = core.dbStore
+
+ @self.app.get(f"{self.core.context}/nodes/list")
+ async def listOfNodes():
+ pipeline = [ #ai slooop
+ # Сортировка для каждого num по убыванию ts
+ {"$sort": {"num": 1, "ts": -1}},
+ # Группировка по num и взятие первого (последнего) документа
+ {"$group": {
+ "_id": "$num",
+ "latest_doc": {"$first": "$$ROOT"}
+ }},
+ # Замена корневого документа
+ {"$replaceRoot": {"newRoot": "$latest_doc"}},
+ # Сортировка результата (опционально)
+ {"$sort": {"num": 1}}
+ ]
+
+ collection = self.dbStore['node_info']
+ c = await collection.aggregate(pipeline)
+ l = await c.to_list()
+ return [NodeDTO(node) for node in l]
+
+ @self.app.get(f"{self.core.context}/nodes/direct")
+ async def listOfDirectNodes():
+ pipeline = [ #ai slooop
+ {"$match": {"hops_away": 0}}, # Фильтруем по списку
+ # Сортировка для каждого num по убыванию ts
+ {"$sort": {"num": 1, "ts": -1}},
+ # Группировка по num и взятие первого (последнего) документа
+ {"$group": {
+ "_id": "$num",
+ "latest_doc": {"$first": "$$ROOT"}
+ }},
+ # Замена корневого документа
+ {"$replaceRoot": {"newRoot": "$latest_doc"}},
+ # Сортировка результата (опционально)
+ {"$sort": {"num": 1}}
+ ]
+
+ collection = self.dbStore['node_info']
+ c = await collection.aggregate(pipeline)
+ l = await c.to_list()
+ return [NodeDTO(node) for node in l]
+
+ @self.app.get(self.core.context + "/nodes/{num}")
+ async def oneNode(num: int):
+ collection = self.dbStore['node_info']
+ c = await collection.find_one(
+ {"num":num},
+ sort=[("ts", -1)]
+ )
+ if c:
+ return NodeDTO(c)
+ else:
+ raise HTMLResponse(status_code=404)
+
+ @self.app.get(self.core.context + "/nodes")
+ async def listOfSelectedNodes(nums: List[int] = Query(None)):
+ pipeline = [
+ {"$match": {"num": {"$in": nums}}}, # Фильтруем по списку
+ {"$sort": {"num": 1, "ts": -1}}, # Сортируем по num и ts (по убыванию)
+ {
+ "$group": {
+ "_id": "$num", # Группируем по num
+ "latest_doc": {"$first": "$$ROOT"} # Берем первую (последнюю по ts)
+ }
+ },
+ {"$replaceRoot": {"newRoot": "$latest_doc"}}, # Восстанавливаем структуру
+ {"$sort": {"num": 1}} # Сортируем результат по num
+ ]
+ collection = self.dbStore['node_info']
+ c = await collection.aggregate(pipeline)
+ l = await c.to_list()
+ return [NodeDTO(node) for node in l]
\ No newline at end of file