Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue #2 and #4. #5

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '37 21 * * 4'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support

steps:
- name: Checkout repository
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality


# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2

# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun

# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.

# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
18 changes: 18 additions & 0 deletions .github/workflows/github-actions-demo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: GitHub Actions Demo
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Mac specific files
.DS_Store

# Logs
logs
*.log
Expand Down Expand Up @@ -56,4 +59,3 @@ typings/

# dotenv environment variables file
.env

28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
# signalk-raspberry-pi-monitoring
Signal K Node Server Plugin for Raspberry PI monitoring (based on signalk-raspberry-pi-temperature)
# signalk-rpi-monitor
Signal K Node Server Plugin for Raspberry PI monitoring (based on signalk-raspberry-pi-temperature and signalk-raspberry-pi-monitoring)

Reports:
- CPU Utilization averaged over the past 5 seconds
- Memory utilization (fraction of total)
- Storage Utilization (fraction of total)
- CPU Temperature (degrees Kelvin)
- GPU Temperature (degrees Kelvin)

In order for CPU utilization to work, you must install the sysstat package.
On a Raspberry Pi you can do this with:

```
sudo apt-get update
sudo apt-get install sysstat
```

Big thanks people who developed the previous generations of monitoring for the Raspberry Pi.
This code is based on:
https://www.npmjs.com/package/signalk-raspberry-pi-monitoring
https://github.com/nmostovoy/signalk-raspberry-pi-monitoring

which is based on:
https://www.npmjs.com/package/signalk-raspberry-pi-temperature
https://github.com/sbender9/signalk-raspberry-pi-temperature
120 changes: 92 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
/*
* Copyright 2018 Nikolay Mostovoy <[email protected]>
* ( This plugin is a modified version of signalk-raspberry-pi-temperature - Copyright 2018 Scott Bender <[email protected]> )
* Copyright 2022 Steve Berl ([email protected])
* This plugin is a modified version of:
* https://github.com/nmostovoy/signalk-raspberry-pi-monitoring
*
* which is a modified version of
* https://github.com/sbender9/signalk-raspberry-pi-temperature
*
* So a big thank you to those who built the foundation on which I am
* adding to.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,27 +22,27 @@
* limitations under the License.
*/

const debug = require('debug')('signalk-raspberry-pi-monitoring')
const debug = require('debug')('signalk-rpi-monitor')
const _ = require('lodash')
const spawn = require('child_process').spawn

const gpu_temp_command = 'sudo /opt/vc/bin/vcgencmd measure_temp'
const cpu_temp_command = 'sudo cat /sys/class/thermal/thermal_zone0/temp'
const cpu_util_mpstat_command = 'sudo mpstat -P ALL\|grep \\\:\|grep -v \\\%'
const mem_util_command = 'sudo free'
const sd_util_command = 'df \/\|grep -v Used\|awk \'\{print \$5\}\'\|awk \'gsub\(\"\%\"\,\"\"\)\''
const gpu_temp_command = 'vcgencmd measure_temp'
const cpu_temp_command = 'cat /sys/class/thermal/thermal_zone0/temp'
const cpu_util_mpstat_command = 'S_TIME_FORMAT=\'ISO\' mpstat -P ALL 5 1 | sed -n 4,8p'
const mem_util_command = 'cat /proc/meminfo'
const sd_util_command = 'df --output=pcent \/\| tail -1 \| awk \'gsub\(\"\%\",\"\"\)\''

module.exports = function(app) {
var plugin = {};
var timer

plugin.id = "signalk-raspberry-pi-monitoring"
plugin.name = "Raspberry PI Monitoring"
plugin.id = "signalk-rpi-monitor"
plugin.name = "RPI Monitor"
plugin.description = "Signal K Node Server Plugin for Raspberry PI monitoring"

plugin.schema = {
type: "object",
description: "The user running node server must have permission to sudo without needing a password",
description: "The user running node server must be in the video group to get GPU temperature",
properties: {
path_cpu_temp: {
title: "SignalK Path for CPU temperature (K)",
Expand Down Expand Up @@ -74,6 +81,43 @@ module.exports = function(app) {
plugin.start = function(options) {
debug("start")

// notify server, once, of units metadata
app.handleMessage(plugin.id, {
updates: [{
meta: [{
path: options.path_cpu_temp,
value: {
units: "K"
}
},
{
path: options.path_gpu_temp,
value: {
units: "K"
}
},
{
path: options.path_cpu_util,
value: {
units: "ratio"
}
},
{
path: options.path_mem_util,
value: {
units: "ratio"
}
},
{
path: options.path_sd_util,
value: {
units: "ratio"
}
},
]
}]
});

function updateEnv() {
getGpuTemperature()
getCpuTemperature()
Expand Down Expand Up @@ -160,7 +204,7 @@ module.exports = function(app) {
}
newPath = newPath + "core." + (Number(spl_line[1])+1).toString()
newPath = newPath + "." + pathArray[(pathArray.length-1)]
var cpu_util_core = ((100 - Number(spl_line[11]))/100).toFixed(2)
var cpu_util_core = ((100 - Number(spl_line[11].replace(/,/, '.')))/100).toFixed(2)
app.handleMessage(plugin.id, {
updates: [
{
Expand All @@ -174,7 +218,7 @@ module.exports = function(app) {
}
else {
debug(`cpu utilisation is ${spl_line[11]}`)
cpu_util_all = ((100 - Number(spl_line[11]))/100).toFixed(2)
cpu_util_all = ((100 - Number(spl_line[11].replace(/,/, '.')))/100).toFixed(2)
app.handleMessage(plugin.id, {
updates: [
{
Expand Down Expand Up @@ -205,24 +249,44 @@ module.exports = function(app) {
memutil.stdout.on('data', (data) => {
debug(`got memory ${data}`)
var mem_util = data.toString().replace(/(\n|\r)+$/, '').split('\n')
mem_util.forEach(function(mem_util_line){
var mem_total
var mem_free
var buffers
var cached
var slab
mem_util.forEach(function(mem_util_line) {
var splm_line = mem_util_line.replace(/ +/g, ' ').split(' ')
if (splm_line[0].toString() === "Mem:"){
var mem_util_per = (Number(splm_line[2])/Number(splm_line[1])).toFixed(2)
app.handleMessage(plugin.id, {
updates: [
{
values: [ {
path: options.path_mem_util,
value: Number(mem_util_per)
}]
}
]
})
}
if (splm_line[0].toString() === "MemTotal:") {
mem_total = Number(splm_line[1])
debug(`got mem_total = ${mem_total}`)
} else if (splm_line[0].toString() === "MemFree:") {
mem_free = Number(splm_line[1])
debug(`got mem_free = ${mem_free}`)
} else if (splm_line[0].toString() === "Buffers:") {
buffers = Number(splm_line[1])
debug(`got buffers = ${buffers}`)
} else if (splm_line[0].toString() === "Cached:") {
cached = Number(splm_line[1])
debug(`got cached = ${cached}`)
} else if (splm_line[0].toString() === "Slab:") {
slab = Number(splm_line[1])
debug(`got slab = ${slab}`)
}
})
var mem_util_per = ((mem_total - (mem_free + buffers + cached + slab))/mem_total).toFixed(2)
debug(`mem_util_per: ${mem_util_per}`)

app.handleMessage(plugin.id, {
updates: [
{
values: [ {
path: options.path_mem_util,
value: Number(mem_util_per)
}]
}
]
})
})

memutil.on('error', (error) => {
console.error(error.toString())
})
Expand Down
34 changes: 18 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
{
"author": {
"name": "Nikolay Mostovoy",
"email": "[email protected]"
"name": "signalk-rpi-monitor",
"version": "1.1.1",
"description": "Signal K Node Server Plugin for Raspberry PI monitoring",
"homepage": "https://github.com/sberl/signalk-rpi-monitor#readme",
"keywords": [
"signalk-node-server-plugin",
"signalk-category-utility",
"signalk-category-hardware"
],
"author": {
"name": "Steve Berl",
"email": "[email protected]"
},
"bugs": {
"url": "https://github.com/nmostovoy/signalk-raspberry-pi-monitoring/issues"
"url": "https://github.com/sberl/signalk-rpi-monitor/issues"
},
"bundleDependencies": false,
"bundleDependencies": [],
"dependencies": {
"debug": "^2.2.0",
"lodash": "^3.10.1"
"lodash": "^4.17.21"
},
"deprecated": false,
"description": "Signal K Node Server Plugin for Raspberry PI monitoring (based on signalk-raspberry-pi-temperature)",
"homepage": "https://github.com/sbender9/signalk-raspberry-pi-monitoring#readme",
"keywords": [
"signalk-node-server-plugin"
],
"license": "ISC",
"license": "Apache-2.0",
"main": "index.js",
"name": "signalk-raspberry-pi-monitoring",
"repository": {
"type": "git",
"url": "git+https://github.com/nmostovoy/signalk-raspberry-pi-monitoring.git"
"url": "https://github.com/sberl/signalk-rpi-monitor.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "1.1.1"
}
}