summaryrefslogtreecommitdiffstats
path: root/py3status/modules/sysdata.py
blob: 7437c0111b80339fc11a22b2994a7d2e7a5b7350 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# -*- coding: utf-8 -*-
"""
Display system RAM and CPU utilization.

Configuration parameters:
    - format: output format string
    - high_threshold: percent to consider CPU or RAM usage as 'high load'
    - med_threshold: percent to consider CPU or RAM usage as 'medium load'

Format of status string placeholders:
    {cpu_temp}         - cpu temperature
    {cpu_usage}        - cpu usage percentage
    {mem_total}        - total memory
    {mem_used}         - used memory
    {mem_used_percent} - used memory percentage

NOTE: If using the {cpu_temp} option, the 'sensors' command should 
be available, provided by the 'lm-sensors' or 'lm_sensors' package.

@author Shahin Azad <ishahinism at Gmail>, shrimpza
"""

import re
import subprocess
from time import time

class GetData:
    """
    Get system status
    """

    def execCMD(self, cmd, arg):
        """
        Take a system command and its argument, then return the result.

        Arguments:
        - `cmd`: system command.
        - `arg`: argument.
        """
        result = subprocess.check_output([cmd, arg])
        result = result.decode('utf-8')
        return result

    def cpu(self):
        """
        Get the cpu usage data from /proc/stat :
          cpu  2255 34 2290 22625563 6290 127 456 0 0
          - user: normal processes executing in user mode
          - nice: niced processes executing in user mode
          - system: processes executing in kernel mode
          - idle: twiddling thumbs
          - iowait: waiting for I/O to complete
          - irq: servicing interrupts
          - softirq: servicing softirqs
          - steal: involuntary wait
          - guest: running a normal guest
          - guest_nice: running a niced guest
        These numbers identify the amount of time the CPU has spent performing
        different kinds of work.  Time units are in USER_HZ
        (typically hundredths of a second)
        """
        with open('/proc/stat', 'r') as fd:
            line = fd.readline()
        cpu_data = line.split()
        total_cpu_time = sum(map(int, cpu_data[1:]))
        cpu_idle_time = int(cpu_data[4])

        #return the cpu total&idle time
        return total_cpu_time, cpu_idle_time

    def memory(self):
        """
        Execute 'free -m' command, grab the memory capacity and used size
        then return; Memory size 'total_mem', Used_mem, and percentage
        of used memory.
        """
        # Run 'free -m' command and make a list from output.
        mem_data = self.execCMD('free', '-m').split()
        mem_index = mem_data.index('Mem:')
        total_mem = int(mem_data[mem_index + 1]) / 1024.
        used_mem = int(mem_data[mem_index + 2]) / 1024.

        # Caculate percentage
        used_mem_percent = int(used_mem / (total_mem / 100))

        # Results are in kilobyte.
        return total_mem, used_mem, used_mem_percent

    def cpuTemp(self):
        """
        Tries to determine CPU temperature using the 'sensors' command.
        Searches for the CPU temperature by looking for a value prefixed
        by either "CPU Temp" or "Core 0" - does not look for or average
        out temperatures of all codes if more than one.
        """

        sensors = subprocess.check_output('sensors', shell=True);
        m = re.search("(Core 0|CPU Temp).+\+(.+).+\(.+", sensors)
        if m:
            cpu_temp = m.groups()[1]
        else:
            cpu_temp = 'Unknown'

        return cpu_temp

class Py3status:
    """
    """
    # available configuration parameters
    cache_timeout = 10
    format = "CPU: {cpu_usage}%, Mem: {mem_used}/{mem_total} GB ({mem_used_percent}%)"
    high_threshold = 75
    med_threshold = 40

    def __init__(self):
        self.data = GetData()
        self.cpu_total = 0
        self.cpu_idle = 0

    def sysData(self, i3s_output_list, i3s_config):
        # get CPU usage info
        cpu_total, cpu_idle = self.data.cpu()
        cpu_usage = 1 - (
            float(cpu_idle-self.cpu_idle) / float(cpu_total-self.cpu_total)
            )
        self.cpu_total = cpu_total
        self.cpu_idle = cpu_idle

        # if specified as a formatting option, also get the CPU temperature
        if '{cpu_temp}' in self.format:
            cpu_temp = self.data.cpuTemp()
        else:
            cpu_temp = ''

        # get RAM usage info
        mem_total, mem_used, mem_used_percent = self.data.memory()

        response = {
            'cached_until': time() + self.cache_timeout,
            'full_text': self.format.format(
                cpu_usage = '%.2f' % (cpu_usage * 100),
                cpu_temp = cpu_temp,
                mem_used = '%.2f' % mem_used,
                mem_total = '%.2f' % mem_total,
                mem_used_percent = '%.2f' % mem_used_percent,
            )
        }

        if max(cpu_usage, mem_used_percent/100) <= self.med_threshold / 100.0:
            response['color'] = i3s_config['color_good']
        elif max(cpu_usage, mem_used_percent/100) <= self.high_threshold / 100.0:
            response['color'] = i3s_config['color_degraded']
        else:
            response['color'] = i3s_config['color_bad']

        return response

if __name__ == "__main__":
    """
    Test this module by calling it directly.
    """
    from time import sleep
    x = Py3status()
    config = {
        'color_bad': '#FF0000',
        'color_degraded': '#FFFF00',
        'color_good': '#00FF00',
    }

    while True:
        print(x.sysData([], config))
        sleep(1)