IP扫描然后做一定的工作并只播放一次MP3

时间:2015-10-16 01:36:19

标签: python loops raspberry-pi

我在这里有以下代码。我想要做的是我想脚本扫描我的IP地址,然后做一些工作。

我的问题是,即使我没有关闭带有主机名IP的手机WIFI,MP3也会每30秒重复一次。

我希望MP3只在脚本找到IP后播放一次,但扫描将继续扫描。

这可能吗?任何帮助将非常感谢

#!/usr/bin/env python
import os, sys
import sched, time
s = sched.scheduler(time.time, time.sleep)
def do_something(sc):
        import os
        hostname = "192.168.254.102" #example
        response = os.system("ping -c 1 " + hostname)
        if response == 0:
                print(hostname, 'is up!')
                os.system("sudo python ../aquarium/nightlight_on.py 1")
                os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
        else:
                print(hostname, 'is down!')
                os.system("sudo python ../aquarium/nightlight_off.py 1")
        sc.enter(160, 1, do_something, (sc,))
s.enter(30, 1, do_something, (s,))
s.run()

1 个答案:

答案 0 :(得分:1)

如果我了解您正在尝试正确执行的操作,则您希望在IP加密的可用性时运行某些行为,并且您正在扫描更改。也就是说,您希望在可用时(在关闭之后)执行一个操作,并在其关闭时(在可用之后)执行不同的操作。如果它继续做以前做过的事情,你就不想做任何事情。

这要求您让函数访问某种state变量。本地变量不起作用,因为您从调度程序重复调用该函数(而不是编写自己的循环)。我认为有三种合理的选择。

最简单的(从当前代码需要更改的角度来看)是使用全局变量。这样的事情会起作用:

import os, sys
import sched, time

state = None

def do_something(sc):
        global state    # global statement is required since we write to the global state
        hostname = "192.168.254.102" #example
        response = os.system("ping -c 1 " + hostname)
        if response == 0 and state != "up":
                state = "up"
                print(hostname, 'is up!')
                os.system("sudo python ../aquarium/nightlight_on.py 1")
                os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
        elif state != "down":
                state = "down"
                print(hostname, 'is down!')
                os.system("sudo python ../aquarium/nightlight_off.py 1")
        sc.enter(160, 1, do_something, (sc,))

s = sched.scheduler(time.time, time.sleep)
s.enter(30, 1, do_something, (s,))
s.run()

全局变量通常被认为是错误的编程实践,因为它们会使全局命名空间变得混乱,尤其是在您无法从任何其他代码访问state变量的情况下。对于像这样的小脚本来说,这并不是什么大问题,但在任何更复杂的代码中执行此操作都是一个坏主意。

下一个替代方法使用闭包来保存状态变量。闭包是内部函数可以访问的外部函数的命名空间。要写入闭包中的变量,您需要使用nonlocal语句,就像前一版本的代码中的global语句一样(这仅在Python 3中可用,它看起来像你正在使用):

import os, sys
import sched, time

def do_something_factory():
    state = None  # state is a local variable in the factory function's namespace

    def do_something(sc):
        nonlocal state    # nonlocal statement lets us write to the outer scope
        hostname = "192.168.254.102" #example
        response = os.system("ping -c 1 " + hostname)
        if response == 0 and state != "up":
                state = "up"
                print(hostname, 'is up!')
                os.system("sudo python ../aquarium/nightlight_on.py 1")
                os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
        elif state != "down":
                state = "down"
                print(hostname, 'is down!')
                os.system("sudo python ../aquarium/nightlight_off.py 1")
        sc.enter(160, 1, do_something, (sc,))
    return do_something # return inner function to caller

s = sched.scheduler(time.time, time.sleep)
s.enter(30, 1, do_something_factory(), (s,))  # call factory function here!
s.run()

最后的方法是使用class来包含函数(作为方法)。状态将存储在一个实例变量中,通过self访问。主脚本代码将创建对象,然后将绑定方法传递给调度程序。如果你愿意的话,你可以将部分或全部代码移到课堂上,但我现在或多或少都会保持相同的设计。

import os, sys
import sched, time

class Doer(object):
    def __init__(self):
        self.state = None

    def do_something(self, sc):
        hostname = "192.168.254.102" #example
        response = os.system("ping -c 1 " + hostname)
        if response == 0 and self.state != "up":
                self.state = "up"
                print(hostname, 'is up!')
                os.system("sudo python ../aquarium/nightlight_on.py 1")
                os.system("omxplayer -o local ../music/jarvis_on.mp3 1")
        elif self.state != "down":
                self.state = "down"
                print(hostname, 'is down!')
                os.system("sudo python ../aquarium/nightlight_off.py 1")
        sc.enter(160, 1, self.do_something, (sc,))

s = sched.scheduler(time.time, time.sleep)
d = Doer()
s.enter(30, 1, d.do_something, (s,))
s.run()