3

I'm trying to make a python code that will autodetect the IP address of Rhode and Schwarz oscilloscope or any test equipment that is connected to my laptop using Ethernet connection.

The IP address of R&S scope at my work place are always starting by the same two numbers 169.254.X.X but the trick is that the IP address of the scope appears in the arp -a report only when I access the scope using its IP address in my the browser. After that the IP shows up in arp report but before nothing the IP address isn't there.

So I wrote the following piece of code thinking it would work but it doesn't since the IP address is not shown before typing the IP address in URL bar of the browser. My goal is to determine the IP address of the scope just by clicking one button on my computer rather than tapping the touchscreen of the scope to find out what is the IP of the equipment.

import tkinter as tk
import time
import threading
import queue
import subprocess

root = tk.Tk()
root.title("SCPI test")
canvas1 = tk.Canvas(root, width=200, height=140, bg='lightsteelblue2', relief='raised')
canvas1.pack()

q1 = queue.Queue()
q2 = queue.Queue()


def auto_detect_ip(num1, num2, num3, num4):
    ping_list = []
    ping_ok_list = []
    t1 = time.time()
    for i in range(num1, num2, -1):
        for j in range(num3, num4, -1):
            temp = "169.254." + str(i) + "." + str(j)
            # temp = "192.168.1.1"
            try:
                p = subprocess.run(["ping", "-n", "1", temp], stdout=subprocess.PIPE, timeout=float(timeout_value))
                # p = subprocess.run(["ping", "-n", "1", temp], stdout=subprocess.PIPE, timeout=0.006)
                return_code = p.returncode
                print("return_code :", return_code)
                if return_code == 0:
                    print("ip_address :", temp)
                    ping_ok_list.append(temp)
                    break
            except subprocess.TimeoutExpired:
                pass
            time.sleep(0.00001)
        else:
            continue
        break
    len_list_ping = len(ping_list)
    print("len_list_ping :", len_list_ping)
    print("ping_ok_list :", ping_ok_list)
    t2 = time.time()
    print("time :", t2 - t1)
    if num4 == 0:
        q1.put(ping_ok_list)
    else:
        q2.put(ping_ok_list) 


def launch_thread():
    print("scan running")
    thread_1 = threading.Thread(target=auto_detect_ip, args=(254, 0, 128, 0))
    thread_2 = threading.Thread(target=auto_detect_ip, args=(254, 0, 254, 128))
    thread_1.setDaemon(True)
    thread_2.setDaemon(True)
    thread_1.start()
    thread_2.start()


def found_rs_scope():
    launch_thread()
    ping_ok_list = q1.get() + q2.get
    print("IP_list :", ping_ok_list)

My solution was to scan each IP address to find the scope one but since the IP doesn't appear in the arp -a in the prompt before accessing the scope through the browser. So there is no match during the scan and the IP isn't found. I think it should be doable but I just don't know how to do it. Also I would like to be able to find the IP address of the scope without requiring admin rights.

Edit: I checked the port used by oscilloscope and it is 5025 as bfris mentioned in his answer. enter image description here

gamer388
  • 53
  • 9
  • Is there any chance you can find the IP Addr from the name? Either from `ping` or `nslookup` – bfris Jul 29 '21 at 16:30

2 Answers2

1

What about a port scanner? In your case, you probably only care about one port (I found a R&S Oscope that listens on 5025). But up to 65536 IP addresses. If you are able to connect to the right port, then you'll probably want to do a *IDN? query to see if it's actually the right instrument.

This will be SLOW though. You have so many addresses to scan. I set the timeout to 0.01 sec so it will take over 10 minutes to scan all of the addresses. I don't even know if 0.010 is a legit timeout.

You might consider asking your IT department to assign a quasi-static address to your scope based on MACID. That could potentially be the fastest solution.

import socket
import sys

part1 = 169
part2 = 254

port = 5025

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(.01)
sock.settimeout(.01)

for part3 in range(1,254+1):
    for part4 in range(1,254+1):
        IP = f'{part1}.{part2}.{part3}.{part4}'
        result = sock.connect_ex((IP, port))
        if result == 0:
            print(f'found open port {port} at {IP}')
            # add additional code here to verify
            # it's the right instrument
            
            # also, probably add break to get out of loop
            # if you found the right instrument
            #
            # break
        else:
            print('nothing at ', IP)
        sock.close()
bfris
  • 5,272
  • 1
  • 20
  • 37
  • Ok thanks for your answer and info. I'll give this a try a see if it does what I want to do. I hope it can be run without admin rights though. If my scope isn't listening on port 5025 then I can add a loop to cycle through I guess. – gamer388 Jul 29 '21 at 03:52
  • Also I notice in your code snippet that you import sys but when I run this code in PyCharm it says unused sys import. What is the purpose of importing sys here ? – gamer388 Jul 29 '21 at 04:12
  • I saw one screenshot where the scope said what its port was on the Web interface. So maybe you can double check that way. I don't know that port scanning is the best solution. It's slow. It's a real shame that arp doesn't work properly. Maybe there is another command for interrogating an Windows DNS server. – bfris Jul 29 '21 at 04:18
  • `import sys` is, in fact, unused. I was thinking that I might use `sys.exit()` to stop the script, but it isn't necessary. – bfris Jul 29 '21 at 04:19
  • Thanks I added a simpledialog prompt to ask for port number in the code so I can adapt to whatever port number the scope is using. I'll see how that goes this morning at work. – gamer388 Jul 29 '21 at 04:46
0

I tried the following code but without success:

import socket
import tkinter as tk

root = tk.Tk()
root.title("R&S IP finder")
canvas1 = tk.Canvas(root, width=200, height=80, bg='lightsteelblue2', relief='raised')
canvas1.pack()


def ip_finder():
    part1 = 169
    part2 = 254
    port = 5025
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket.setdefaulttimeout(.01)
    sock.settimeout(.01)
    print("starting scan on port {}".format(port))
    for part3 in range(1, 254 + 1):
        for part4 in range(1, 254 + 1):
            ip_address = f'{part1}.{part2}.{part3}.{part4}'
            # print(ip_address)
            result = sock.connect_ex((ip_address, port))
            if result == 0:
                print(ip_address)
                break
            else:
                continue
    print("scan finished.")
    sock.close()


Launch_prgm = tk.Button(text="Device detect", command=ip_finder, bg='green', fg='white', font=('helvetica', 12, 'bold'))
canvas1.create_window(100, 35, window=Launch_prgm)
root.mainloop()

Here is the output of the code running on my laptop which is connected to the oscilloscope (rhode and schwarz) that I want to find the IP before typing it in the browser to control the scope or find it in the scope interface itself. enter image description here

Apparently the condition if result == 0: is never true. I guess I need admin rights to do what I want. What a shame then.

gamer388
  • 53
  • 9
  • Does the Web Interface listen on port 80 or 5025? If it listens on 80, you can try to scan that port. This might lend credence to a theory that there is some sort of Windows security thing. Also, what happens if you turn `Device Identication` option on? That looks promising.... Finally, you could look for a setting on the scope to always have the remote interface on. – bfris Jul 30 '21 at 14:57