Is your home server offline again? Has your IP camera stopped streaming video? Is the internet completely down or is just one website not loading? To get instant answers to these questions, you can create a simple yet effective monitoring system.
In this article, we'll set up a script that supports Windows, macOS, and Linux. It will regularly check the availability of any internet resources and send data to the VizIoT server.
For the most accurate monitoring, our script uses three different checking methods. This is important because a device might respond to "ping" while its specific service (like a website or video stream) may not be working.
554 on an IP camera (RTSP) or port 3306 on a database is working. If the port is open, the service is alive.To run the script, we need two key libraries:
ping package: A convenient wrapper that allows Node.js to use system connectivity utilities. It saves us from writing complex code for each OS.viziot-mqtt-client-nodejs package: Official client for the VizIoT platform. It handles all MQTT protocol work: encryption, connection maintenance, and reliable data transmission to your charts.The script doesn't just send "raw" numbers—it helps you become a "network detective." Looking at the chart in VizIoT, you can immediately identify the source of the problem:
For measurement accuracy: The script takes three measurements for each target and calculates the arithmetic mean. This eliminates random errors (single packet "dropouts") and gives you a smooth, realistic latency chart.
Before we move to the code, take a look at what the finished widget looks like.
What you can track with this configuration:
How to interpret the chart:
This approach allows you to instantly determine the source of the problem: your local network, internet provider, or a specific remote service.
Seeing a problem on the chart is good, but getting an instant notification about it is even better. VizIoT allows you to set up alerts that will come to you via Telegram or email as soon as one of your resources becomes unavailable, as well as when it comes back online.

Interested? Let's set up such a system step by step.
Our code is cross-platform and works equally well on Windows, Linux, and macOS.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install 24
Create a folder and install the necessary packages we mentioned above:
mkdir ./VizIoTPinger && cd ./VizIoTPinger
npm init -y
npm i ping viziot-mqtt-client-nodejs
Create a main.js file.
nano ./main.js
Note the runMeasurements function—it's responsible for triple-checking for data accuracy.
const net = require('net')
const ping = require('ping')
const http = require('http')
const https = require('https')
const viziotMQTT = require('viziot-mqtt-client-nodejs')
// ================= SETTINGS =================
// Paste your VizIoT device key and password here
const DEVICE_KEY = '_____________'
const DEVICE_PASSWORD = '______________________'
const CHECK_INTERVAL_SEC = 3 * 60 // Interval between checks in seconds
// ================= TARGETS =================
// key — the parameter name that will appear in VizIoT
// target — IP address, domain, or URL
// port — port (optional, for TCP ping)
const TARGETS = [
{ key: 'home_router_latency', target: '192.168.2.1' },
{ key: 'cloudflare_dns_latency', target: '1.1.1.1' },
{ key: 'google_dns_latency', target: '8.8.8.8' },
{ key: 'google_latency', target: 'google.com' },
{ key: 'ipCamera_latency', target: '192.168.0.158', port: 554 },
// { key: 'my_website', target: 'https://my-site.com' },
]
// ================= MQTT =================
const client = new viziotMQTT(DEVICE_KEY, DEVICE_PASSWORD)
// ================= UTILITIES =================
// Auxiliary function for performing measurements
async function runMeasurements(measureFn, attempts = 3) {
const results = []
for (let i = 0; i < attempts; i++) {
results.push(await measureFn())
}
const valid = results.filter((r) => r > -1)
if (valid.length === 0) {
return { latency: -1 }
}
const avg = valid.reduce((a, b) => a + b, 0) / valid.length
return { latency: Math.round(avg) }
}
// Function for checking ICMP (ping)
function checkICMP(item) {
const measure = () =>
new Promise((resolveRequest) => {
ping.promise
.probe(item.target, {
timeout: 5,
})
.then(function (res) {
resolveRequest(res.alive ? res.time : -1)
})
})
return runMeasurements(measure)
}
// Function for checking TCP
function checkTCP(item) {
const measure = () =>
new Promise((resolveRequest) => {
const socket = new net.Socket()
const start = Date.now()
socket.setTimeout(5000)
socket.connect(item.port, item.target, () => {
socket.destroy()
resolveRequest(Date.now() - start)
})
socket.on('error', (e) => {
console.log('Socket error:', e)
socket.destroy()
resolveRequest(-1)
})
socket.on('timeout', () => {
console.log('Socket timeout')
socket.destroy()
resolveRequest(-1)
})
})
return runMeasurements(measure)
}
// Function for checking HTTP/HTTPS
function checkURL(item) {
const measure = () =>
new Promise((resolveRequest) => {
const start = Date.now()
const lib = item.target.startsWith('https') ? https : http
const req = lib.get(item.target, { timeout: 5000 }, (res) => {
res.resume()
resolveRequest(Date.now() - start)
})
req.on('error', () => resolveRequest(-1))
req.on('timeout', () => {
req.destroy()
resolveRequest(-1)
})
})
return runMeasurements(measure)
}
// ================= CHECKS =================
let isWorking = false
async function runChecks() {
// Preventing overlapping launches
if (isWorking) return
isWorking = true
console.log('🔍 Starting checks...')
const payload = {}
for (const item of TARGETS) {
let result
if (item.target.startsWith('http')) {
result = await checkURL(item)
} else {
if (item.port) {
result = await checkTCP(item)
} else {
result = await checkICMP(item)
}
}
payload[item.key] = result.latency
const status = result.latency >= 0 ? '✅' : '❌'
console.log(`${status} ${item.key}: latency=${result.latency} ms`)
}
isWorking = false
console.log('📨 Sending data to VizIoT:', payload)
// client.sendDataToVizIoT(payload, (err) => {
// if (err) console.error('Error sending data:', err)
// })
}
// ================= START =================
function main() {
console.log('🔗 Try Connected to VizIoT')
// client.connect(() => {
console.log('✅ Connected')
console.log('🚀 Pinger starting…')
runChecks()
setInterval(runChecks, CHECK_INTERVAL_SEC * 1000)
// })
}
main()
To make your script run 24/7 and start automatically after computer reboot, use the PM2 process manager:
npm install pm2 -g
pm2 start main.js --name "VizIoTPinger"
pm2 save
pm2 startup
Now that data is coming in, all that's left is to set up the interface.
home_router_latency, google_latency, ipCamera_latencyipCamera_latency).Detailed instructions on setting up notifications can be found in this article.
Now that data is being transmitted, go to the VizIoT dashboard:
ipCamera_latency).Value < 0 (this means the service is unavailable).Now, as soon as your camera goes "offline" or a website stops loading, you'll receive a message about it within a minute!