【问题标题】:How to incorporate the IP address of a device into a Python script if the address changes如果地址更改,如何将设备的 IP 地址合并到 Python 脚本中
【发布时间】:2019-09-23 23:04:26
【问题描述】:

我有一个 Python 脚本,它可以从智能插头检索测量数据,以便我可以在我的 Rasbperry Pi 上将其可视化。

这个命令获取数据

send_hs_command("192.168.1.26", 9999, b'{"emeter":{"get_realtime":{}}}')

这就是定义

def send_hs_command(address, port, cmd):
    data = b""

    tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        tcp_sock.connect((address, port))
        tcp_sock.send(encrypt(cmd))
        data = tcp_sock.recv(2048)
    except socket.error:        
        print(time.asctime( time.localtime(time.time()) ), "Socket closed.", file=sys.stderr)
    finally:
        tcp_sock.close()
    return data

我的问题是,如果我把智能插头带到别处,它就会有 一个新的 IP 地址,这意味着我必须继续在我的 Python 脚本上重写它。这不是我的选择。什么是最简单的解决方案?谢谢

【问题讨论】:

  • 我猜你可以通过 iface 名称获取 IP 地址,不是吗?也许看看这篇帖子stackoverflow.com/questions/24196932/… 会有所帮助。您甚至可以使用一些网络嗅探 python 包(如 scapy)从 MAC 地址获取 IP 地址。
  • @danlor - 您正在尝试解决与所询问的问题不同的问题。提问者需要获取智能插头的地址,而不是 pi 的地址。
  • @ChrisStratton,你是对的,我误读了这个问题。 iface-name 方法会给他在给定子网中的 pi 的地址,而不是智能插头的地址。但是,MAC 方法仍然有效。

标签: python raspberry-pi ip ip-address iot


【解决方案1】:

我没有 Pi 来运行它。

如果目标(智能插头)的IP地址是可变的,你能不使用预先确定的主机名(位于'/etc/hostname')来代替吗?

socket 库提供了一些方便的函数;

您可以先使用 gethostbyaddr 如果您还没有主机名信息,则获取主机名。 然后从那时起,您可以使用已知的主机名并使用 create_connection 建立连接。

但是,如果您想使用更动态的东西;我建议使用 MAC 地址作为密钥。 请注意,在 Raspberry Pi 上运行可能依赖于 tcpdumpscapy 可能会耗尽 CPU。 请看下面的sn-p:

import socket
import time
import sys
from scapy.all import *


def send_hs_command(address, port, cmd):
    data = b""
    tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        tcp_sock.connect((address, port))
        tcp_sock.send(encrypt(cmd))
        data = tcp_sock.recv(2048)
    except socket.error:
        print(time.asctime( time.localtime(time.time()) ), "Socket closed.", file=sys.stderr)
    finally:
        tcp_sock.close()
    print(data)
    return data


def get_ip_from_mac():
    # Match ARP requests
    packet_list = sniff(filter="arp", count=10) # increase number of arp counts
    for i in packet_list:
        # Show all ARP requests
        # print(i[Ether].src, "is broadcasting IP", i[ARP].psrc)
        if (i[ARP].hwsrc == '00:0c:29:b6:f4:be'): # target MAC address
            return (True, i[ARP].psrc)
    return (False, '')


def main():
    result = get_ip_from_mac()
    if result[0] == True:
        print("Succeeded to reach server")
        send_hs_command(result[1], 22, b'{"emeter":{"get_realtime":{}}}')
    else:
        # logic to retry or graciously fail
        print("Failed to reach server")


if __name__== "__main__":
    main()

【讨论】:

  • 非常感谢。我会测试它并让你知道。您的建议是因为 MAC 地址始终相同,对吧?
  • 是的,他是。如果您使用的是 Linux,您可以设置一个 udev 规则,根据设备的 MAC(或其他参数)重命名 iface,因此您也可以通过 iface 名称获取 IP 地址,正如我所说的。
  • 嗨,我收到此错误File "mactoip.py", line 5, in <module> from scapy.all import * ImportError: No module named 'scapy'
  • pip install scapy是你的朋友,也安装tcpdump
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
  • 2013-01-26
  • 2017-01-05
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多