14 changed files with 213 additions and 12 deletions
@ -1,3 +1,6 @@ |
|||
Created on MiniMeshT (https://github.com/allanrbo/MiniMeshT) |
|||
|
|||
need install fastapi uvicorn |
|||
need install fastapi uvicorn |
|||
|
|||
python3 -m pip install --user --break-system-packages pyserial-asyncio |
|||
python3 -m pip install --user --break-system-packages uvicorn[standart] fastapi |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@ |
|||
{ |
|||
"/mesh/api": { |
|||
"target": "http://127.0.0.1:8868/", |
|||
"secure": false |
|||
}, |
|||
"/mesh/ws": { |
|||
"target": "http://127.0.0.1:8868/", |
|||
"secure": false, |
|||
"ws":true |
|||
}} |
|||
@ -0,0 +1,50 @@ |
|||
import {Component} from "@angular/core"; |
|||
import { |
|||
AVAILABLE, |
|||
ERR, |
|||
MeshtasticService, |
|||
NOT_CONNECTED, |
|||
RECONNECT, |
|||
WAIT_CONFIG |
|||
} from "../../services/MeshtasticService"; |
|||
|
|||
@Component({ |
|||
selector: "app-meshtastic-header", |
|||
template: ` |
|||
<div style="display: flex; align-items: center; justify-content: flex-start; padding-left: 45px"> |
|||
<p>MY</p> |
|||
<p>NODES</p> |
|||
<p *ngFor="let c of meshtastic.channels">{{c.name}}</p> |
|||
</div> |
|||
<div style="padding-top: 2.5%"> |
|||
<!--<router-outlet></router-outlet>--> |
|||
</div> |
|||
<div class="footer"> |
|||
<div style="display: flex; justify-content: space-between; height: 100%"> |
|||
<div class="footer-text" style="width: 30%"> |
|||
<span>{{getMeshState()}}</span> |
|||
</div> |
|||
<div class="footer-text" style="width: 49%"> |
|||
<span>{{meshtastic.getMyMesh().name}}</span> |
|||
</div> |
|||
<div class="footer-text" style="width: 20%"> |
|||
<span>{{meshtastic.nodes.length}} nodes</span> |
|||
</div> |
|||
</div> |
|||
</div>` |
|||
}) |
|||
export class MeshtasticHeaderComponent { |
|||
constructor(public meshtastic: MeshtasticService) { |
|||
} |
|||
|
|||
getMeshState(): string { |
|||
switch (this.meshtastic.state) { |
|||
case NOT_CONNECTED: return "Не подключен"; |
|||
case WAIT_CONFIG: return "Ожидания конфигурации"; |
|||
case AVAILABLE: return "Доступен"; |
|||
case ERR: return "Ошибка модуля"; |
|||
case RECONNECT: return "Переподключение"; |
|||
default: return "Хуй знает"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,101 @@ |
|||
import {Injectable} from "@angular/core"; |
|||
import {WebSocketSubject} from "rxjs/internal/observable/dom/WebSocketSubject"; |
|||
import {webSocket} from "rxjs/webSocket"; |
|||
import {BehaviorSubject} from "rxjs"; |
|||
|
|||
export const WS_EVENT_CHANNEL = 0; |
|||
export const WS_EVENT_NODE = 1; |
|||
export const WS_EVENT_STATE = 2; |
|||
export const WS_EVENT_MESSAGE = 3; |
|||
export const WS_EVENT_MYID = 4; |
|||
|
|||
export const WS_TYPE_INIT = 0; |
|||
export const WS_TYPE_NEW = 1; |
|||
export const WS_TYPE_FRONTEND = 2; |
|||
|
|||
export const NOT_CONNECTED = 0; |
|||
export const WAIT_CONFIG = 1; |
|||
export const AVAILABLE = 2; |
|||
export const ERR = 3; |
|||
export const RECONNECT = 4; |
|||
|
|||
interface MeshNodeShort { |
|||
id: number; |
|||
name: string; |
|||
} |
|||
|
|||
interface MeshChannel { |
|||
index: number; |
|||
name: string; |
|||
} |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class MeshtasticService { |
|||
private socket$?: WebSocketSubject<any>; |
|||
public channels: MeshChannel[] = []; |
|||
public nodes: MeshNodeShort[] = []; |
|||
public messages = new BehaviorSubject('{}') |
|||
public state: number = NOT_CONNECTED; |
|||
public meshId: number = 0; |
|||
|
|||
|
|||
constructor() { |
|||
this.connect(); |
|||
} |
|||
|
|||
public getMyMesh(): MeshNodeShort { |
|||
if (this.meshId == 0) |
|||
return {name: "Неизвестно", id: 0}; |
|||
else { |
|||
let m: MeshNodeShort[] = this.nodes.filter(node => node.id == this.meshId); |
|||
// @ts-ignore
|
|||
return m.length > 0 ? m.pop() : {name: "Неизвестно", id: 0}; |
|||
} |
|||
} |
|||
|
|||
private connect() { |
|||
this.socket$ = webSocket(`ws://${location.host}/mesh/ws`) |
|||
this.socket$.subscribe( |
|||
(parsed: {type: number, event: number, data: any}) => { |
|||
switch (parsed.event) { |
|||
case WS_EVENT_MYID: { |
|||
this.meshId = parsed.data; |
|||
break; |
|||
} |
|||
case WS_EVENT_NODE: { |
|||
const node: MeshNodeShort = parsed.data; |
|||
const s_node: MeshNodeShort[] = this.nodes.filter(n => n.id == node.id) |
|||
if (s_node.length == 0) |
|||
this.nodes.push(node) |
|||
else { |
|||
let idx = this.nodes.indexOf(s_node[0]) |
|||
this.nodes[idx] = node |
|||
} |
|||
break; |
|||
} |
|||
|
|||
case WS_EVENT_STATE: { |
|||
this.state = parsed.data; |
|||
break; |
|||
} |
|||
|
|||
case WS_EVENT_CHANNEL: { |
|||
const channel: MeshChannel = parsed.data; |
|||
const s_channel: MeshChannel[] = this.channels.filter(ch => ch.index == channel.index); |
|||
if (s_channel.length == 0) |
|||
this.channels.push(channel) |
|||
else { |
|||
let idx = this.channels.indexOf(s_channel[0]); |
|||
this.channels[idx] = channel; |
|||
} |
|||
break; |
|||
} |
|||
|
|||
} |
|||
}, |
|||
(err) => {} |
|||
) |
|||
} |
|||
} |
|||
@ -1,3 +1,6 @@ |
|||
#!/bin/bash |
|||
sudo systemctl stop nginx |
|||
sudo rm -rf /var/www/html |
|||
sudo cp -r /home/pipboy/Pipboy3Kmark4/pipboyUI/dist/pipboy-ui /var/www/html |
|||
sudo cp -r /home/pipboy/Pipboy3Kmark4/pipboyUI/dist/pipboy-ui /var/www/html |
|||
sudo nginx -t |
|||
sudo systemctl start nginx |
|||
Loading…
Reference in new issue