commit
1cf94c8a55
|
|
@ -73,6 +73,9 @@ Run app using Docker:
|
|||
user@user-laptop:~$ cd oktopus/deploy/compose
|
||||
user@user-laptop:~/oktopus/deploy/compose$ COMPOSE_PROFILES=nats,controller,mqtt,stomp,ws,adapter,frontend,portainer docker compose up -d
|
||||
</pre>
|
||||
UI will open at port 3000:
|
||||
<img src="https://github.com/OktopUSP/oktopus/assets/83298718/c05bcaea-db87-4705-acb9-94d0711cffcf"/>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<h4>Device test agent (obuspa):</h4>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type StatusCount struct {
|
|||
type GeneralInfo struct {
|
||||
MqttRtt string
|
||||
WebsocketsRtt string
|
||||
StompRtt string
|
||||
ProductClassCount []entity.ProductClassCount
|
||||
StatusCount StatusCount
|
||||
VendorsCount []entity.VendorsCount
|
||||
|
|
@ -73,28 +74,34 @@ func (a *Api) generalInfo(w http.ResponseWriter, r *http.Request) {
|
|||
result.ProductClassCount = productclasscount.Msg
|
||||
|
||||
now := time.Now()
|
||||
_, err = bridge.NatsReq[time.Duration](
|
||||
_, err = bridge.NatsReqWithoutHttpSet[time.Duration](
|
||||
local.NATS_WS_ADAPTER_SUBJECT_PREFIX+"rtt",
|
||||
[]byte(""),
|
||||
w,
|
||||
a.nc,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
result.WebsocketsRtt = time.Until(now).String()
|
||||
}
|
||||
|
||||
now = time.Now()
|
||||
_, err = bridge.NatsReq[time.Duration](
|
||||
local.NATS_MQTT_ADAPTER_SUBJECT_PREFIX+"rtt",
|
||||
_, err = bridge.NatsReqWithoutHttpSet[time.Duration](
|
||||
local.NATS_STOMP_ADAPTER_SUBJECT_PREFIX+"rtt",
|
||||
[]byte(""),
|
||||
w,
|
||||
a.nc,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
if err == nil {
|
||||
result.StompRtt = time.Until(now).String()
|
||||
}
|
||||
|
||||
now = time.Now()
|
||||
_, err = bridge.NatsReqWithoutHttpSet[time.Duration](
|
||||
local.NATS_MQTT_ADAPTER_SUBJECT_PREFIX+"rtt",
|
||||
[]byte(""),
|
||||
a.nc,
|
||||
)
|
||||
if err == nil {
|
||||
result.MqttRtt = time.Until(now).String()
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).Encode(result)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -172,3 +172,35 @@ func NatsReq[T entity.DataType](
|
|||
|
||||
return answer, nil
|
||||
}
|
||||
|
||||
func NatsReqWithoutHttpSet[T entity.DataType](
|
||||
subj string,
|
||||
body []byte,
|
||||
nc *nats.Conn,
|
||||
) (*entity.MsgAnswer[T], error) {
|
||||
|
||||
var answer *entity.MsgAnswer[T]
|
||||
|
||||
msg, err := nc.Request(subj, body, local.NATS_REQUEST_TIMEOUT)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(msg.Data, &answer)
|
||||
if err != nil {
|
||||
|
||||
var errMsg *entity.MsgAnswer[*string]
|
||||
err = json.Unmarshal(msg.Data, &errMsg)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Bad answer message formatting: ", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Printf("Error message received, msg: %s, code: %d", *errMsg.Msg, errMsg.Code)
|
||||
return nil, errNatsMsgReceivedWithErrorData
|
||||
}
|
||||
|
||||
return answer, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const (
|
|||
NATS_ADAPTER_SUBJECT = "adapter.usp.v1."
|
||||
NATS_WS_SUBJECT_PREFIX = "ws.usp.v1."
|
||||
NATS_WS_ADAPTER_SUBJECT_PREFIX = "ws-adapter.usp.v1."
|
||||
NATS_STOMP_ADAPTER_SUBJECT_PREFIX = "stomp-adapter.usp.v1."
|
||||
DEVICE_SUBJECT_PREFIX = "device.usp.v1."
|
||||
BUCKET_NAME = "devices-auth"
|
||||
BUCKET_DESCRIPTION = "Devices authentication"
|
||||
|
|
|
|||
1
frontend/public/assets/mtp/boot-stomp.svg
Normal file
1
frontend/public/assets/mtp/boot-stomp.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M508.784 449.96c-24.003 11.18-48.31 25.674-72.133 43.11 22.442-32.53 47.493-58.012 73.402-76.778l27.18-271.844c11.906-55.18-57.034-79.69-145.858-68.53h.005c-69.085 8.68-150.046 38.63-214.47 94.45l66.83 379.773 3.967 121.142 116.998 16.885 33.498-78.006 46.518 82.623c160.062 18.85 282.558-2.402 343.51-43.52 12.164-125.97-86.014-283.128-279.445-199.302zm330.62 203.593c10.84 6.508 16.718 13.45 16.718 20.657 0 37.11-155.22 67.193-346.687 67.193S162.748 711.32 162.748 674.21c0-7.242 5.935-14.214 16.875-20.75-44.516 13.278-70.606 29.376-70.606 46.73 0 45.503 179.242 82.392 400.34 82.392s400.338-36.887 400.338-82.393c0-17.314-25.968-33.377-70.292-46.637zm-674.198 4.535h-94.85l50.264 22.353c9.533-7.97 24.7-15.483 44.587-22.352zm-56.188 42.1c0-7.466 4.844-14.7 13.897-21.58l-91.203 52.79 91.21-9.63c-9.048-6.878-13.904-14.11-13.904-21.58zm31.116 31.897L81.846 821.01l129.345-65.846c-29.515-6.777-53.666-14.563-71.056-23.08zm97.566 28.617L216.27 894.04l122.614-119.286c-37.23-3.612-71.312-8.37-101.184-14.052zm134.48 16.915l23.31 154.804 101.68-149.88c-43.792-.27-85.82-1.984-124.99-4.924zm151.694 4.904l112.24 153.3 13.78-158.464c-39.43 3.044-81.81 4.84-126.02 5.165zm159.22-8.08L804.46 894.048l-21.488-133.72c-29.47 5.68-63.102 10.46-99.88 14.112zm197.003-43.12c-17.226 8.68-41.43 16.62-71.19 23.52l129.97 66.167-58.78-89.686zm29.6-31.13c0 7.4-4.77 14.57-13.66 21.393l92.98 9.816-108.47-62.78-.115.605c18.86 9.558 29.265 20.01 29.265 30.964zm-56.19-42.102c20.404 7.048 35.85 14.774 45.33 22.977l51.667-22.977h-96.996z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
1
frontend/public/assets/mtp/websocket.svg
Normal file
1
frontend/public/assets/mtp/websocket.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg height="193" preserveAspectRatio="xMidYMid" viewBox="0 0 256 193" width="256" xmlns="http://www.w3.org/2000/svg"><path d="m192.440223 144.644612h31.779888v-76.3052736l-35.804782-35.8047822-22.472322 22.4723223 26.497216 26.4972158zm31.86374 15.93187h-46.286275-64.566001l-26.497216-26.497216 11.2361612-11.236161 21.8853588 21.885359h45.028496l-44.357681-44.441533 11.320014-11.3200132 44.35768 44.3576812v-45.0284968l-21.801506-21.8015067 11.152309-11.1523092-55.09073-55.3422863h-54.3360633-56.3485097l31.6960367 31.6960367v.0838519h.1677039 65.572224l23.2269894 23.2269899-33.9600388 33.9600393-23.2269899-23.2269899v-18.028169h-31.7798886v31.192925l55.0068785 55.0068781-22.3884704 22.388471 35.8047822 35.804782h54.336063 101.54471z" fill="#ffffff"/></svg>
|
||||
|
After Width: | Height: | Size: 766 B |
|
|
@ -143,12 +143,6 @@ const Page = () => {
|
|||
container
|
||||
spacing={3}
|
||||
>
|
||||
<Grid
|
||||
xs={12}
|
||||
sm={6}
|
||||
lg={3}
|
||||
>
|
||||
</Grid>
|
||||
<Grid
|
||||
xs={12}
|
||||
sm={6}
|
||||
|
|
@ -168,6 +162,20 @@ const Page = () => {
|
|||
>
|
||||
<OverviewTasksProgress
|
||||
sx={{ height: '100%' }}
|
||||
mtp={"Conexão STOMP"}
|
||||
type={"stomp"}
|
||||
value={generalInfo.StompRtt}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
xs={12}
|
||||
sm={6}
|
||||
lg={3}
|
||||
>
|
||||
<OverviewTasksProgress
|
||||
sx={{ height: '100%' }}
|
||||
mtp={"Conexão MQTT"}
|
||||
type={"mqtt"}
|
||||
value={generalInfo.MqttRtt}
|
||||
/>
|
||||
</Grid>
|
||||
|
|
@ -176,6 +184,12 @@ const Page = () => {
|
|||
sm={6}
|
||||
lg={3}
|
||||
>
|
||||
<OverviewTasksProgress
|
||||
sx={{ height: '100%' }}
|
||||
mtp={"Conexão Websockets"}
|
||||
type={"websocket"}
|
||||
value={generalInfo.WebsocketsRtt}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
xs={12}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import ListBulletIcon from '@heroicons/react/24/solid/ListBulletIcon';
|
||||
import ExclamationTriangle from '@heroicons/react/24/solid/ExclamationTriangleIcon';
|
||||
import Signal from '@heroicons/react/24/solid/SignalIcon';
|
||||
import Image from 'next/image';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
|
|
@ -12,13 +13,67 @@ import {
|
|||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
|
||||
export const OverviewTasksProgress = (props) => {
|
||||
var { value, sx } = props;
|
||||
var { value, mtp, sx, type } = props;
|
||||
var valueRaw;
|
||||
if( value !== undefined) {
|
||||
valueRaw = value.substring(1);
|
||||
console.log("rtt:", valueRaw)
|
||||
}
|
||||
|
||||
const formatMilliseconds = (timeString) => {
|
||||
|
||||
if (timeString === "") {
|
||||
return "";
|
||||
}
|
||||
// Regular expression to extract value and unit
|
||||
const regex = /^(\d+(\.\d+)?)\s*([mµ]?s|s)?$/;
|
||||
|
||||
// Extract value and unit
|
||||
const matches = timeString.match(regex);
|
||||
if (!matches) {
|
||||
return "Invalid time format";
|
||||
}
|
||||
|
||||
let value = parseFloat(matches[1]);
|
||||
const unit = matches[3] || "ms";
|
||||
|
||||
// Convert units to milliseconds
|
||||
switch (unit) {
|
||||
case "s":
|
||||
value *= 1000;
|
||||
break;
|
||||
case "µs":
|
||||
value /= 1000;
|
||||
break;
|
||||
default:
|
||||
// For "ms", do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
// Round the number to two decimal places
|
||||
const roundedValue = value.toFixed(2);
|
||||
|
||||
return `${roundedValue}ms`;
|
||||
}
|
||||
|
||||
const showIcon = (mtpType) => {
|
||||
if (valueRaw === "") {
|
||||
return <SvgIcon><ExclamationTriangle></ExclamationTriangle></SvgIcon>
|
||||
}
|
||||
switch (mtpType) {
|
||||
case "mqtt":
|
||||
return <SvgIcon><Signal/></SvgIcon>
|
||||
case "stomp":
|
||||
return <Image src="/assets/mtp/boot-stomp.svg" alt="STOMP" width={24} height={24} />;
|
||||
case "websocket":
|
||||
return <Image src="/assets/mtp/websocket.svg" alt="WebSocket" width={24} height={24} />;
|
||||
default:
|
||||
return <ExclamationTriangle />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card sx={sx}>
|
||||
<CardContent>
|
||||
|
|
@ -34,10 +89,10 @@ export const OverviewTasksProgress = (props) => {
|
|||
gutterBottom
|
||||
variant="overline"
|
||||
>
|
||||
Conexão MQTT
|
||||
{mtp}
|
||||
</Typography>
|
||||
<Typography variant="h4">
|
||||
{valueRaw}
|
||||
{formatMilliseconds(valueRaw)}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Avatar
|
||||
|
|
@ -47,14 +102,12 @@ export const OverviewTasksProgress = (props) => {
|
|||
width: 56
|
||||
}}
|
||||
>
|
||||
<SvgIcon>
|
||||
<Signal />
|
||||
</SvgIcon>
|
||||
{showIcon(type)}
|
||||
</Avatar>
|
||||
</Stack>
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<LinearProgress
|
||||
value={80}
|
||||
value={valueRaw ? 80 : 0}
|
||||
variant="determinate"
|
||||
/>
|
||||
</Box>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user