Author Topic: New Dashboard Socket Server  (Read 380 times)

0 Members and 2 Guests are viewing this topic.

razwall

  • Administrator
  • Jr. Member
  • *****
  • Posts: 58
    • View Profile
New Dashboard Socket Server
« on: March 14, 2025, 12:54:55 PM »
Socket Service:

#!/usr/bin/perl
use strict;
use warnings;
use Net::WebSocket::Server;
use JSON;

# Store previous network stats
my %prev_net_stats = get_network_usage();

# Start WebSocket server
Net::WebSocket::Server->new(
    listen => 3000,
    on_connect => sub {
        my ($conn) = @_;
        my %last_check = (
            cpu => time(),
            memory => time(),
            network => time(),
            connections => time(),
            disk => time()
        );
        my %intervals = (
            cpu => 2,
            memory => 5,
            network => 3,
            connections => 10,
            disk => 10
        );

        $conn->on(utf8 => sub {
            my $msg = shift;
            my $config = eval { decode_json($msg) };
            return unless ref $config eq 'HASH';

            # Set custom intervals from the client
            $intervals{cpu}        = $config->{cpu}        if exists $config->{cpu};
            $intervals{memory}    = $config->{memory}    if exists $config->{memory};
            $intervals{network}    = $config->{network}    if exists $config->{network};
            $intervals{connections}= $config->{connections} if exists $config->{connections};
            $intervals{disk}      = $config->{disk}      if exists $config->{disk};
        });

        while ($conn->is_open) {
            my $now = time();

            # Check and send updates based on intervals
            if ($now - $last_check{cpu} >= $intervals{cpu}) {
                $conn->send(encode_json({ cpu => get_cpu_usage() }));
                $last_check{cpu} = $now;
            }
            if ($now - $last_check{memory} >= $intervals{memory}) {
                $conn->send(encode_json({ memory => get_memory_usage() }));
                $last_check{memory} = $now;
            }
            if ($now - $last_check{network} >= $intervals{network}) {
                $conn->send(encode_json({ network => get_network_stats() }));
                $last_check{network} = $now;
            }
            if ($now - $last_check{connections} >= $intervals{connections}) {
                $conn->send(encode_json({ connections => get_network_connections() }));
                $last_check{connections} = $now;
            }
            if ($now - $last_check{disk} >= $intervals{disk}) {
                $conn->send(encode_json({ disk => get_disk_usage() }));
                $last_check{disk} = $now;
            }

            # Sleep for a short time to prevent high CPU usage
            select(undef, undef, undef, 0.5);
        }
    }
)->start;

### **Helper Functions**
sub get_cpu_usage {
    open my $fh, '<', "/proc/stat" or return;
    my $line = <$fh>;
    close $fh;

    my @cpu_data = (split /\s+/, $line)[1..8];
    my $total = 0;
    my $idle = $cpu_data[3];

    $total += $_ for @cpu_data;

    state $prev_total = $total;
    state $prev_idle = $idle;

    my $diff_total = $total - $prev_total;
    my $diff_idle = $idle - $prev_idle;

    $prev_total = $total;
    $prev_idle = $idle;

    return sprintf("%.2f", 100 * (1 - $diff_idle / $diff_total));
}

sub get_memory_usage {
    open my $fh, '<', "/proc/meminfo" or return;
    my %mem;
   
    while (<$fh>) {
        if (/^(MemTotal|MemAvailable):\s+(\d+)/) {
            $mem{$1} = $2;
        }
    }
    close $fh;

    return sprintf("%.2f", 100 * (1 - $mem{MemAvailable} / $mem{MemTotal}));
}

sub get_network_usage {
    open my $fh, '<', "/proc/net/dev" or return;
    my %stats;

    while (<$fh>) {
        if (/^\s*(\w+):\s*(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)/) {
            my ($iface, $rx_bytes, $tx_bytes) = ($1, $2, $3);
            $stats{$iface} = { download => $rx_bytes, upload => $tx_bytes };
        }
    }
    close $fh;
   
    return %stats;
}

sub get_network_stats {
    my %current = get_network_usage();
    my %stats_diff;

    foreach my $iface (keys %current) {
        if (exists $prev_net_stats{$iface}) {
            $stats_diff{$iface} = {
                download => $current{$iface}{download} - $prev_net_stats{$iface}{download},
                upload => $current{$iface}{upload} - $prev_net_stats{$iface}{upload},
            };
        } else {
            $stats_diff{$iface} = { download => 0, upload => 0 };
        }
    }

    %prev_net_stats = %current;
    return \%stats_diff;
}

sub get_network_connections {
    my @connections;
    my $cmd = `ss -tan 2>/dev/null` || `netstat -tan 2>/dev/null`;

    foreach my $line (split /\n/, $cmd) {
        if ($line =~ /\b(LISTEN|ESTABLISHED|TIME_WAIT|CLOSE_WAIT|SYN_SENT)\b/) {
            push @connections, $line;
        }
    }

    return \@connections;
}

sub get_disk_usage {
    my @disks;
    my $cmd = `df -h --output=source,pcent,target | tail -n +2`;

    foreach my $line (split /\n/, $cmd) {
        if ($line =~ /^(\S+)\s+(\d+%)\s+(\S+)/) {
            push @disks, { filesystem => $1, used => $2, mount => $3 };
        }
    }

    return \@disks;
}

razwall

  • Administrator
  • Jr. Member
  • *****
  • Posts: 58
    • View Profile
Re: New Dashboard Socket Server
« Reply #1 on: March 14, 2025, 12:56:03 PM »
Tick Polling Request:
{
  "cpu": 2,
  "memory": 5,
  "network": 3,
  "connections": 10,
  "disk": 15
}

razwall

  • Administrator
  • Jr. Member
  • *****
  • Posts: 58
    • View Profile
Re: New Dashboard Socket Server
« Reply #2 on: March 14, 2025, 12:56:51 PM »
Response output:

{ "cpu": "14.23" }
{ "network": { "eth0": { "download": 13456, "upload": 7890 } } }
{ "memory": "62.50" }
{ "connections": [
    "tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:*",
    "tcp ESTABLISHED 0 0 192.168.1.10:54321 192.168.1.20:80"
] }
{ "disk": [
    { "filesystem": "/dev/sda1", "used": "45%", "mount": "/" },
    { "filesystem": "/dev/sdb1", "used": "78%", "mount": "/data" }
] }