API Reference

__main__

IoT Health CLI Entry.

bin

cli

IoT Health CLI.

cameras()

Command for the cameras info.

Source code in iothealth/bin/cli.py
64
65
66
67
@click.command()
def cameras():
    """Command for the cameras info."""
    click.echo(device_health.DeviceHealth().cameras())

capacity()

Command for the device capacity.

Source code in iothealth/bin/cli.py
52
53
54
55
@click.command()
def capacity():
    """Command for the device capacity."""
    click.echo(device_health.DeviceHealth().capacity())

cli()

CLI entry point.

Source code in iothealth/bin/cli.py
10
11
12
13
@click.group()
def cli():
    """CLI entry point."""
    pass

main()

Entry point for the CLI.

Source code in iothealth/bin/cli.py
81
82
83
def main():
    """Entry point for the CLI."""
    cli()

memory()

Command for the memory info.

Source code in iothealth/bin/cli.py
46
47
48
49
@click.command()
def memory():
    """Command for the memory info."""
    click.echo(device_health.DeviceHealth().memory())

os_info()

Command for OS info.

Source code in iothealth/bin/cli.py
34
35
36
37
@click.command()
def os_info():
    """Command for OS info."""
    click.echo(device_health.DeviceHealth().operating_system())

platform()

Command for platform info.

Source code in iothealth/bin/cli.py
22
23
24
25
@click.command()
def platform():
    """Command for platform info."""
    click.echo(device_health.DeviceHealth().device_platform())

processor_arch()

Command for the CPU info.

Source code in iothealth/bin/cli.py
28
29
30
31
@click.command()
def processor_arch():
    """Command for the CPU info."""
    click.echo(device_health.DeviceHealth().processor_architecture())

processors()

Command for processors info.

Source code in iothealth/bin/cli.py
40
41
42
43
@click.command()
def processors():
    """Command for processors info."""
    click.echo(device_health.DeviceHealth().processors())

summary()

Command for the health summary.

Source code in iothealth/bin/cli.py
16
17
18
19
@click.command()
def summary():
    """Command for the health summary."""
    click.echo(device_health.DeviceHealth().summary())

temperature()

Command for the device temperature.

Source code in iothealth/bin/cli.py
58
59
60
61
@click.command()
def temperature():
    """Command for the device temperature."""
    click.echo(device_health.DeviceHealth().temperature())

device_health

IoT Health.

DeviceHealth

Bases: BaseHealth

Generic class for a device health info.

Source code in iothealth/device_health.py
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
class DeviceHealth(_base_health.BaseHealth):
    """Generic class for a device health info."""

    _current_device_cache: Optional[_base_health.BaseHealth] = None

    # Override
    @classmethod
    def summary(cls) -> dict:
        """Provide the health information for the current device.

        Returns
        -------
        `dict`
            All the available health information as a key-value dictionary.
        """
        return DeviceHealth._current_device().summary()

    # Override
    @classmethod
    def device_platform(cls) -> str:
        """Provide the device platform info."""
        return DeviceHealth._current_device().device_platform()

    # Override
    @classmethod
    def processor_architecture(cls) -> str:
        """Provide the device CPU info."""
        return DeviceHealth._current_device().processor_architecture()

    # Override
    @classmethod
    def operating_system(cls) -> str:
        """Provide the device OS info."""
        return DeviceHealth._current_device().operating_system()

    # Override
    @classmethod
    def processors(cls) -> dict:
        """Provice the device processors info."""
        return DeviceHealth._current_device().processors()

    # Override
    @classmethod
    def memory(cls) -> dict:
        """Provide the device memory info."""
        return DeviceHealth._current_device().memory()

    # Override
    @classmethod
    def capacity(cls) -> dict:
        """Provide the device disk usage info."""
        return DeviceHealth._current_device().capacity()

    # Override
    @classmethod
    def temperature(cls) -> dict:
        """Provide the device temperature."""
        return DeviceHealth._current_device().temperature()

    # Override
    @classmethod
    def cameras(cls) -> dict:
        """Provide the cameras info."""
        return DeviceHealth._current_device().cameras()

    @classmethod
    def _current_device(cls) -> _base_health.BaseHealth:
        if cls._current_device_cache is None:
            if "Raspberry Pi" in raspberry_pi.RaspberryPi().device_platform():
                cls._current_device_cache = raspberry_pi.RaspberryPi()
            else:
                cls._current_device_cache = (
                    linux.Linux()
                )  # Jetson Nano is also included
        return cls._current_device_cache

cameras() classmethod

Provide the cameras info.

Source code in iothealth/device_health.py
72
73
74
75
@classmethod
def cameras(cls) -> dict:
    """Provide the cameras info."""
    return DeviceHealth._current_device().cameras()

capacity() classmethod

Provide the device disk usage info.

Source code in iothealth/device_health.py
60
61
62
63
@classmethod
def capacity(cls) -> dict:
    """Provide the device disk usage info."""
    return DeviceHealth._current_device().capacity()

device_platform() classmethod

Provide the device platform info.

Source code in iothealth/device_health.py
30
31
32
33
@classmethod
def device_platform(cls) -> str:
    """Provide the device platform info."""
    return DeviceHealth._current_device().device_platform()

memory() classmethod

Provide the device memory info.

Source code in iothealth/device_health.py
54
55
56
57
@classmethod
def memory(cls) -> dict:
    """Provide the device memory info."""
    return DeviceHealth._current_device().memory()

operating_system() classmethod

Provide the device OS info.

Source code in iothealth/device_health.py
42
43
44
45
@classmethod
def operating_system(cls) -> str:
    """Provide the device OS info."""
    return DeviceHealth._current_device().operating_system()

processor_architecture() classmethod

Provide the device CPU info.

Source code in iothealth/device_health.py
36
37
38
39
@classmethod
def processor_architecture(cls) -> str:
    """Provide the device CPU info."""
    return DeviceHealth._current_device().processor_architecture()

processors() classmethod

Provice the device processors info.

Source code in iothealth/device_health.py
48
49
50
51
@classmethod
def processors(cls) -> dict:
    """Provice the device processors info."""
    return DeviceHealth._current_device().processors()

summary() classmethod

Provide the health information for the current device.

Returns

dict All the available health information as a key-value dictionary.

Source code in iothealth/device_health.py
18
19
20
21
22
23
24
25
26
27
@classmethod
def summary(cls) -> dict:
    """Provide the health information for the current device.

    Returns
    -------
    `dict`
        All the available health information as a key-value dictionary.
    """
    return DeviceHealth._current_device().summary()

temperature() classmethod

Provide the device temperature.

Source code in iothealth/device_health.py
66
67
68
69
@classmethod
def temperature(cls) -> dict:
    """Provide the device temperature."""
    return DeviceHealth._current_device().temperature()

linux

General Linux health info on x86 platform.

Linux

Bases: BaseHealth

Health information for general Linux devices.

Source code in iothealth/linux.py
 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
173
174
175
176
177
178
class Linux(_base_health.BaseHealth):
    """Health information for general Linux devices."""

    # Override
    @classmethod
    def device_platform(cls) -> str:
        """Get the system information.

        Returns
        -------
        `str`
            An empty string is returned if the platform is unknown.
            Otherwise, return the device platform info.
        """
        result = subprocess.run(
            ["cat", "/proc/version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
        if result.stderr:
            return str()
        return result.stdout.decode("utf-8").strip()

    # Override
    @classmethod
    def processor_architecture(cls) -> str:
        """Get the processor architecture.

        Returns
        -------
        `str`
            An empty string is returned if the processor architecture is
            unknown. Otherwise, return the processor type, e.g., `x86_64`.
        """
        return platform.processor()

    # Override
    @classmethod
    def operating_system(cls) -> str:
        """Get the OS info.

        Returns
        -------
        `str`
            An empty string is returned if the OS is unknown.
            Otherwise, return the processor type, e.g., `Linux`.
        """
        return platform.system()

    # Override
    @classmethod
    def processors(cls) -> dict:
        """Get the detail processor information as JSON format.

        Returns
        -------
        `dict`
            The detail information is as the following format:
        .. code-block:: JSON
            {
                "physical_cores": 4,
                "total_cores": 4,
                "max_frequency": 1400.00,
                "min_frequency": 600.00,
                "current_frequency": 1400.00,
                "usage_per_core": [
                    {
                        "core": 0,
                        "usage": 0.2
                    },
                    {
                        "core": 1,
                        "usage": 0.0
                    },
                    {
                        "core": 2,
                        "usage": 0.0
                    },
                    {
                        "core": 3,
                        "usage": 0.0
                    }
                ],
                "total_usage": 0.1
            }
        """
        frequency = psutil.cpu_freq()
        usages = list()
        for index, usage in enumerate(psutil.cpu_percent(percpu=True, interval=1)):
            each_cpu = {"core": index, "usage": usage}
            usages.append(each_cpu)

        result = {
            "physical_cores": psutil.cpu_count(logical=False),
            "total_cores": psutil.cpu_count(logical=True),
            "max_frequency": frequency.max,
            "min_frequency": frequency.min,
            "current_frequency": frequency.current,
            "usage_per_core": usages,
            "total_usage": psutil.cpu_percent(),
        }
        return result

    # Override
    @classmethod
    def memory(cls) -> dict:
        """Get virtual memory usage in bytes.

        Returns
        -------
        `dict`
            Usages returned as a `dictionary` with keys `total`, `available`,
            and `used`.
        """
        result = psutil.virtual_memory()
        return {
            "total": result.total,
            "available": result.available,
            "used": result.used,
        }

    # Override
    @classmethod
    def capacity(cls) -> dict:
        """Get the current disk capacity usage in bytes.

        Returns
        -------
        `dict`
            Usages returned as a `dictionary` with keys `total`, `available`,
            and `used`.
        """
        result = shutil.disk_usage("/")
        return {"total": result.total, "available": result.free, "used": result.used}

    # Override
    @classmethod
    def temperature(cls) -> dict:
        """Provide the device temperature."""
        thermal_zone_path = "/sys/devices/virtual/thermal/thermal_zone"
        zone_temps = {}
        for zone_number in range(0, 6):
            zone_dir = thermal_zone_path + str(zone_number)
            zname = subprocess.run(
                ["cat", zone_dir + "/type"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            if zname.stderr:
                continue
            ztemp = subprocess.run(
                ["cat", zone_dir + "/temp"],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            if ztemp.stderr:
                continue
            zone_temps[zname.stdout.decode("utf-8").strip()] = ztemp.stdout.decode(
                "utf-8"
            ).strip()
        return zone_temps

    # Override
    @classmethod
    def cameras(cls) -> dict:
        """Provide cameras information."""
        return {}

cameras() classmethod

Provide cameras information.

Source code in iothealth/linux.py
175
176
177
178
@classmethod
def cameras(cls) -> dict:
    """Provide cameras information."""
    return {}

capacity() classmethod

Get the current disk capacity usage in bytes.

Returns

dict Usages returned as a dictionary with keys total, available, and used.

Source code in iothealth/linux.py
134
135
136
137
138
139
140
141
142
143
144
145
@classmethod
def capacity(cls) -> dict:
    """Get the current disk capacity usage in bytes.

    Returns
    -------
    `dict`
        Usages returned as a `dictionary` with keys `total`, `available`,
        and `used`.
    """
    result = shutil.disk_usage("/")
    return {"total": result.total, "available": result.free, "used": result.used}

device_platform() classmethod

Get the system information.

Returns

str An empty string is returned if the platform is unknown. Otherwise, return the device platform info.

Source code in iothealth/linux.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@classmethod
def device_platform(cls) -> str:
    """Get the system information.

    Returns
    -------
    `str`
        An empty string is returned if the platform is unknown.
        Otherwise, return the device platform info.
    """
    result = subprocess.run(
        ["cat", "/proc/version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    if result.stderr:
        return str()
    return result.stdout.decode("utf-8").strip()

memory() classmethod

Get virtual memory usage in bytes.

Returns

dict Usages returned as a dictionary with keys total, available, and used.

Source code in iothealth/linux.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
@classmethod
def memory(cls) -> dict:
    """Get virtual memory usage in bytes.

    Returns
    -------
    `dict`
        Usages returned as a `dictionary` with keys `total`, `available`,
        and `used`.
    """
    result = psutil.virtual_memory()
    return {
        "total": result.total,
        "available": result.available,
        "used": result.used,
    }

operating_system() classmethod

Get the OS info.

Returns

str An empty string is returned if the OS is unknown. Otherwise, return the processor type, e.g., Linux.

Source code in iothealth/linux.py
49
50
51
52
53
54
55
56
57
58
59
@classmethod
def operating_system(cls) -> str:
    """Get the OS info.

    Returns
    -------
    `str`
        An empty string is returned if the OS is unknown.
        Otherwise, return the processor type, e.g., `Linux`.
    """
    return platform.system()

processor_architecture() classmethod

Get the processor architecture.

Returns

str An empty string is returned if the processor architecture is unknown. Otherwise, return the processor type, e.g., x86_64.

Source code in iothealth/linux.py
36
37
38
39
40
41
42
43
44
45
46
@classmethod
def processor_architecture(cls) -> str:
    """Get the processor architecture.

    Returns
    -------
    `str`
        An empty string is returned if the processor architecture is
        unknown. Otherwise, return the processor type, e.g., `x86_64`.
    """
    return platform.processor()

processors() classmethod

Get the detail processor information as JSON format.

Returns

dict The detail information is as the following format: .. code-block:: JSON { "physical_cores": 4, "total_cores": 4, "max_frequency": 1400.00, "min_frequency": 600.00, "current_frequency": 1400.00, "usage_per_core": [ { "core": 0, "usage": 0.2 }, { "core": 1, "usage": 0.0 }, { "core": 2, "usage": 0.0 }, { "core": 3, "usage": 0.0 } ], "total_usage": 0.1 }

Source code in iothealth/linux.py
 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
@classmethod
def processors(cls) -> dict:
    """Get the detail processor information as JSON format.

    Returns
    -------
    `dict`
        The detail information is as the following format:
    .. code-block:: JSON
        {
            "physical_cores": 4,
            "total_cores": 4,
            "max_frequency": 1400.00,
            "min_frequency": 600.00,
            "current_frequency": 1400.00,
            "usage_per_core": [
                {
                    "core": 0,
                    "usage": 0.2
                },
                {
                    "core": 1,
                    "usage": 0.0
                },
                {
                    "core": 2,
                    "usage": 0.0
                },
                {
                    "core": 3,
                    "usage": 0.0
                }
            ],
            "total_usage": 0.1
        }
    """
    frequency = psutil.cpu_freq()
    usages = list()
    for index, usage in enumerate(psutil.cpu_percent(percpu=True, interval=1)):
        each_cpu = {"core": index, "usage": usage}
        usages.append(each_cpu)

    result = {
        "physical_cores": psutil.cpu_count(logical=False),
        "total_cores": psutil.cpu_count(logical=True),
        "max_frequency": frequency.max,
        "min_frequency": frequency.min,
        "current_frequency": frequency.current,
        "usage_per_core": usages,
        "total_usage": psutil.cpu_percent(),
    }
    return result

temperature() classmethod

Provide the device temperature.

Source code in iothealth/linux.py
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
@classmethod
def temperature(cls) -> dict:
    """Provide the device temperature."""
    thermal_zone_path = "/sys/devices/virtual/thermal/thermal_zone"
    zone_temps = {}
    for zone_number in range(0, 6):
        zone_dir = thermal_zone_path + str(zone_number)
        zname = subprocess.run(
            ["cat", zone_dir + "/type"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        if zname.stderr:
            continue
        ztemp = subprocess.run(
            ["cat", zone_dir + "/temp"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        if ztemp.stderr:
            continue
        zone_temps[zname.stdout.decode("utf-8").strip()] = ztemp.stdout.decode(
            "utf-8"
        ).strip()
    return zone_temps

raspberry_pi

Raspberry Pi health information.

RaspberryPi

Bases: Linux

Check Raspberry Pi health and status.

Source code in iothealth/raspberry_pi.py
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
class RaspberryPi(linux.Linux):
    """Check Raspberry Pi health and status."""

    # Override
    @classmethod
    def device_platform(cls) -> str:
        """Get the IoT device platform.

        Returns
        -------
        `str`
            An empty string is returned if the platform is unknown.
            Otherwise, return the device platform info, e.g.,
            `Raspberry Pi 3 Model B Plus Rev 1.3`.
        """
        result = subprocess.run(
            ["cat", "/sys/firmware/devicetree/base/model"],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        if result.stderr:
            return str()
        return result.stdout.decode("utf-8").strip()

    # Override
    @classmethod
    def temperature(cls) -> dict:
        """Get the device's temperature.

        Returns
        -------
        float
            The device temperature, e.g., 54.8.
            The temperature unit is Celsius.

        Raises
        ------
        `RuntimeError`
            Raised if the temperature info is not available.
        """
        VCGENGCMD = "vcgencmd"
        vcgencmd_path = shutil.which(VCGENGCMD)

        if not vcgencmd_path:
            raise RuntimeError(f"No {VCGENGCMD} command found.")

        result = subprocess.run(
            [vcgencmd_path, "measure_temp"],
            capture_output=True,
            text=True,
        )
        if not result.stderr:
            temp = re.search("\\d+\\.\\d+", result.stdout)
            if temp:
                return {"chip": temp.group(0)}

        return {}

    # Override
    @classmethod
    def cameras(cls) -> dict:
        """Provide the cameras info."""
        return {}

cameras() classmethod

Provide the cameras info.

Source code in iothealth/raspberry_pi.py
71
72
73
74
@classmethod
def cameras(cls) -> dict:
    """Provide the cameras info."""
    return {}

device_platform() classmethod

Get the IoT device platform.

Returns

str An empty string is returned if the platform is unknown. Otherwise, return the device platform info, e.g., Raspberry Pi 3 Model B Plus Rev 1.3.

Source code in iothealth/raspberry_pi.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@classmethod
def device_platform(cls) -> str:
    """Get the IoT device platform.

    Returns
    -------
    `str`
        An empty string is returned if the platform is unknown.
        Otherwise, return the device platform info, e.g.,
        `Raspberry Pi 3 Model B Plus Rev 1.3`.
    """
    result = subprocess.run(
        ["cat", "/sys/firmware/devicetree/base/model"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    if result.stderr:
        return str()
    return result.stdout.decode("utf-8").strip()

temperature() classmethod

Get the device's temperature.

Returns

float The device temperature, e.g., 54.8. The temperature unit is Celsius.

Raises

RuntimeError Raised if the temperature info is not available.

Source code in iothealth/raspberry_pi.py
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
@classmethod
def temperature(cls) -> dict:
    """Get the device's temperature.

    Returns
    -------
    float
        The device temperature, e.g., 54.8.
        The temperature unit is Celsius.

    Raises
    ------
    `RuntimeError`
        Raised if the temperature info is not available.
    """
    VCGENGCMD = "vcgencmd"
    vcgencmd_path = shutil.which(VCGENGCMD)

    if not vcgencmd_path:
        raise RuntimeError(f"No {VCGENGCMD} command found.")

    result = subprocess.run(
        [vcgencmd_path, "measure_temp"],
        capture_output=True,
        text=True,
    )
    if not result.stderr:
        temp = re.search("\\d+\\.\\d+", result.stdout)
        if temp:
            return {"chip": temp.group(0)}

    return {}