Python Forum
Check if clients are online with ips stored in json [SOLVED]
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Check if clients are online with ips stored in json [SOLVED]
#1
Hello everybody,

I have a script which should do something (to make an example, I let it create a folder). Therefore I defined a function which does just that:

def folder():
    path = os.getcwd()
    newPath = path+"/tmp"

    os.mkdir(newPath)
But I only want my function to be executed when at least one of my clients are online. The ip addresses are defined in a json file:

[
  {
    "Name": "Client 1",
    "ip": "192.168.1.2"
  },
  {
    "Name": "Client 2",
    "ip": "192.168.1.3"
  }
]
Now I want to define a new function which checks all ip addresses. The question I have is, how do I get the ips from my json and ping them one after another to check if at least one of them is online and if they are execute my folder-function? This is all I have so far:

def ipCheck():
    f = open('clients.json')
    data = json.load(f)

    for i in data:
        print(i)

    f.close()
Reply
#2
Hi @AlphaInc ,
I understand you have two problems:
  1. You need to read a JSON file,
  2. You need to know if an IP address responds.

You dit almost right reading the JSON file, but you missed a detail. Look at the file: it starts with "[" so it is a list. There is one comma, so the list contains two items. The items start with "{" so they are dictionaries. You want the IP-address, and you see these addresses have key "ip".
So to extract these adresses you should do someting like:
import json

with open("clients.json") as f:
    data = json.load(f)
    for i in data:
        print(i["ip"])
Now for the ping(). You could use pythonping, but if I understand the manual right, you need to be superuser to run a script using pythonping. I consider this to be bad practice.
So you need to use the default ping on your computer. On Windows you should execute one ping with "ping /n 1 192.168.1.2". On Linux-like systems you need to use "-c" (count) instead of "/n". So you could define a function like this:
from subprocess import call, DEVNULL
import platform

def ping(host_or_ip: str) -> bool :
    """ping() executes:
    on windows:
        ping /n 1 host_or_ip
    on Linux or Mac:
        ping -c 1 host_or_ip
    Meaning: execute one ping to host_or_ip.
    Returns True if host_or_ip responded,
    else False.
    """
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)
Please show us how you use these building blocks to create your program. Let us know if you run into troubles.
Reply
#3
icmplib is cool✨
We had a Thread about this before ping program in Python.
So to write a example on how it can be done,this also works as an unprivileged user.
import asyncio
from icmplib import async_multiping
import json

def read_json():
    ip_lst = []
    with open("clients.json") as f:
        data = json.load(f)
        # Add one to test online status
        ip_lst.append('python-forum.io')
        for ip in data:
            ip_lst.append(ip["ip"])
    return ip_lst

async def are_alive(addresses):
    check_ip = []
    hosts = await async_multiping(addresses, privileged=False)
    for host in hosts:
        if host.is_alive:
            print(f'{host.address} is up!')
            check_ip.append('up')
        else:
            print(f'{host.address} is down!')
            check_ip.append('down')
    return check_ip

if __name__ == '__main__':
    ips = read_json()
    status = asyncio.run(are_alive(ips))
    if 'up' in status:
        print('One host is online')
        # Do someting
    else:
        print('No host is online')
Output:
172.67.168.227 is up! 192.168.1.2 is down! 192.168.1.3 is down! One host is online
ibreeden likes this post
Reply
#4
(Jun-26-2022, 05:15 PM)ibreeden Wrote: Hi @AlphaInc ,
I understand you have two problems:
  1. You need to read a JSON file,
  2. You need to know if an IP address responds.

You dit almost right reading the JSON file, but you missed a detail. Look at the file: it starts with "[" so it is a list. There is one comma, so the list contains two items. The items start with "{" so they are dictionaries. You want the IP-address, and you see these addresses have key "ip".
So to extract these adresses you should do someting like:
import json

with open("clients.json") as f:
    data = json.load(f)
    for i in data:
        print(i["ip"])
Now for the ping(). You could use pythonping, but if I understand the manual right, you need to be superuser to run a script using pythonping. I consider this to be bad practice.
So you need to use the default ping on your computer. On Windows you should execute one ping with "ping /n 1 192.168.1.2". On Linux-like systems you need to use "-c" (count) instead of "/n". So you could define a function like this:
from subprocess import call, DEVNULL
import platform

def ping(host_or_ip: str) -> bool :
    """ping() executes:
    on windows:
        ping /n 1 host_or_ip
    on Linux or Mac:
        ping -c 1 host_or_ip
    Meaning: execute one ping to host_or_ip.
    Returns True if host_or_ip responded,
    else False.
    """
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)
Please show us how you use these building blocks to create your program. Let us know if you run into troubles.

Okay, now I understand how to read the json file. But I still have trouble to ping the ips I wrote in my json file. This is my current code:

from subprocess import call, DEVNULL
import platform
import json
import sys
import os

def folder():
    path = os.getcwd()
    newPath = path+"/tmp"

    os.mkdir(newPath)

def ip_check(host_or_ip: str) -> bool :
    with open("clients.json") as f:
        data = json.load(f)
        for i in data:
            print(i["ip"])

    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

ip_check(host_or_ip)

#End
sys.exit()
After executing the script I get this error message:

Traceback (most recent call last):
  File "/home/pi/system/debug/modules/ipCheck/v0.6.py", line 31, in <module>
    ip_check(host_or_ip)
NameError: name 'host_or_ip' is not defined
Reply
#5
No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os


def folder():
    path = os.getcwd()
    newPath = path + "/tmp"
    os.mkdir(newPath)

def ping(host_or_ip: str) -> bool :
    """ping(): execute one ping to host_or_ip.
    Returns True if host_or_ip responded,
    else False.
    """
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

responding_hosts = 0
with open("clients.json") as f:
    data = json.load(f)
    for i in data:
        print(f"pinging: {i['ip']}")
        if ping(i["ip"]):
            responding_hosts += 1

print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
    folder()
Reply
#6
(Jun-27-2022, 07:16 AM)ibreeden Wrote: No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os


def folder():
    path = os.getcwd()
    newPath = path + "/tmp"
    os.mkdir(newPath)

def ping(host_or_ip: str) -> bool :
    """ping(): execute one ping to host_or_ip.
    Returns True if host_or_ip responded,
    else False.
    """
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

responding_hosts = 0
with open("clients.json") as f:
    data = json.load(f)
    for i in data:
        print(f"pinging: {i['ip']}")
        if ping(i["ip"]):
            responding_hosts += 1

print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
    folder()

Okay nice, this worked great!
Sorry, but I have one last question. I tried to check for two different json files (one contains a list of IPs which should be offline and one which should be online) but I'm running into some problems once again:

#!/usr/bin/env python3

#Imports
from subprocess import call, DEVNULL
import platform
import json
import os

#IP Configuration
responding_clients1 = 0
responding_clients2 = 0

#Folder Creation
def folder():
    path = os.getcwd()
    newPath = path + "/tmp"
    os.mkdir(newPath)

#Pinp Configuration
def ping(host_or_ip: str) -> bool :
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

#Clients1 Check
with open("clients1.json") as f1:
    data1 = json.load(f1)
    for i in data1:
        if ping(i["ip"]):
            responding_clients1 += 1

#Clients2 Check
with open("clients2.json") as f2:
    data2 = json.load(f2)
    for i in data2:
        if ping(i["ip"]):
            responding_clients2 += 1

#ToDo
if responding_clients1 > 0 :
    if responding_clients2 == 0:
        folder()

#End
sys.exit()
And I get this error message:

Traceback (most recent call last):
  File "/home/pi/system/debug/ipCheck/v1.0.py", line 37, in <module>
    data2 = json.load(f2)
  File "/usr/local/lib/python3.10/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.10/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 3 (char 112)
Reply
#7
(Jun-27-2022, 08:02 AM)AlphaInc Wrote:
(Jun-27-2022, 07:16 AM)ibreeden Wrote: No. You must read the ip addresses from the json file one by one, and for each address test if it responds.
from subprocess import call, DEVNULL
import platform
import json
import os


def folder():
    path = os.getcwd()
    newPath = path + "/tmp"
    os.mkdir(newPath)

def ping(host_or_ip: str) -> bool :
    """ping(): execute one ping to host_or_ip.
    Returns True if host_or_ip responded,
    else False.
    """
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

responding_hosts = 0
with open("clients.json") as f:
    data = json.load(f)
    for i in data:
        print(f"pinging: {i['ip']}")
        if ping(i["ip"]):
            responding_hosts += 1

print(f"Number of responding hosts: {responding_hosts}")
if responding_hosts > 0 :
    folder()

Okay nice, this worked great!
Sorry, but I have one last question. I tried to check for two different json files (one contains a list of IPs which should be offline and one which should be online) but I'm running into some problems once again:

#!/usr/bin/env python3

#Imports
from subprocess import call, DEVNULL
import platform
import json
import os

#IP Configuration
responding_clients1 = 0
responding_clients2 = 0

#Folder Creation
def folder():
    path = os.getcwd()
    newPath = path + "/tmp"
    os.mkdir(newPath)

#Pinp Configuration
def ping(host_or_ip: str) -> bool :
    if platform.system().lower() == "windows":
        countoption = "/n"
    else:
        countoption = "-c"
    return not call(["ping", countoption, "1", host_or_ip],
                    stdout=DEVNULL, stderr=DEVNULL)

#Clients1 Check
with open("clients1.json") as f1:
    data1 = json.load(f1)
    for i in data1:
        if ping(i["ip"]):
            responding_clients1 += 1

#Clients2 Check
with open("clients2.json") as f2:
    data2 = json.load(f2)
    for i in data2:
        if ping(i["ip"]):
            responding_clients2 += 1

#ToDo
if responding_clients1 > 0 :
    if responding_clients2 == 0:
        folder()

#End
sys.exit()
And I get this error message:

Traceback (most recent call last):
  File "/home/pi/system/debug/ipCheck/v1.0.py", line 37, in <module>
    data2 = json.load(f2)
  File "/usr/local/lib/python3.10/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/usr/local/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/lib/python3.10/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 3 (char 112)

Nevermind, there was a missing comma in my second .json file. Thank you all for your help Smile
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [solved] list content check paul18fr 6 615 Jan-04-2024, 11:32 AM
Last Post: deanhystad
  Loop through json file and reset values [SOLVED] AlphaInc 2 1,962 Apr-06-2023, 11:15 AM
Last Post: AlphaInc
  Response.json list indices must be integers or slices, not str [SOLVED] AlphaInc 4 6,186 Mar-24-2023, 08:34 AM
Last Post: fullytotal
  [SOLVED] [sqilte3] Check if column not empty? Winfried 5 1,066 Jan-28-2023, 12:53 PM
Last Post: Winfried
  Stream via socket with multiple clients principemestizo 0 1,433 Nov-01-2021, 06:25 PM
Last Post: principemestizo
  Duplex Named Pipe with Python Server and C# Clients raybowman 1 2,337 Dec-03-2020, 09:58 PM
Last Post: Gribouillis
  Saving and accessing data from different clients SheeppOSU 1 1,946 Jul-28-2019, 02:15 AM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020