【问题标题】:XBMC notification image (coming from IP cam) not updatingXBMC 通知图像(来自 IP cam)未更新
【发布时间】:2014-06-16 07:21:23
【问题描述】:

我的电视上连接了一个 XBMC 盒子。此外,我有 2 个 Foscam IP 摄像机,用于监控我的两个小女儿。

不久前,我认为编写几个脚本会很酷,这样当 Foscam 的一个警报触发时,我会在 XBMC 上收到通知以及来自相关 Foscam 摄像头的实时图像。有了这个,我可以一边看电视,一边密切关注孩子们。

所以,在 XBMC 机器上,我运行了一个 shell 脚本,它每秒检查一次 Foscam 警报状态。如果触发警报,它会向 XBMC 发送命令以触发 XBMC 脚本,暂停检查 30 秒,然后继续检查警报状态。 XBMC 脚本会显示一个 30 秒的通知,其中包含我的一个女儿的名字(取决于触发的相机)和她们的可爱照片,以及来自相关 Foscam 的实时快照,每半秒更新一次。

这一切都很好,非常棒:) 但是,上周我升级了 Foscam 的固件。新固件的唯一变化(固件描述中提到)是将相机的HTTP授权方法从basic更改为digest。从那以后,我的 XBMC 脚本一直存在问题。

首先,这是脚本的当前版本:

# Import the XBMC/XBMCGUI modules.
from requests.auth import HTTPDigestAuth
import xbmc, xbmcgui, xbmcvfs, xbmcaddon
import sys, os, requests, time


# Class to manage the notification image
class CamView(xbmcgui.WindowDialog):

    urlpath   = "/snapshot.cgi?resolution=16"
    imagename = "snapshot.jpg"

    def __init__(self, camname,camport,idx,username,password):

        # Construct correct URL
        self.baseurl = 'http://' + camname + 'cam:' + camport

        # Cams use digest authentication
        self.auth = HTTPDigestAuth(username, password)

        # Set
        path = xbmc.translatePath('special://profile/addon_data/%s' % xbmcaddon.Addon().getAddonInfo('id'))
        if not xbmcvfs.exists(path):
            xbmcvfs.mkdir(path)
        self.imagefile = os.path.join(path, self.imagename)

        # Message
        self.msg = {
            "1": camname.capitalize() + ' moved',
            "3": camname.capitalize() + ' made a sound',
        }.get(idx, camname.capitalize() + 'cam fired alarm')

        # set the initial image before the window is shown
        self.image = xbmcgui.ControlImage(870, 383, 380, 253, "")
        self.addControl(self.image)


    def update_image(self):

        f = requests.get(self.baseurl+self.urlpath, auth=self.auth)
        with open(self.imagefile, "wb") as local_file:
            local_file.write(f.content)

        self.image.setImage("")
        self.image.setImage(self.imagefile)

    def __enter__(self):
        return self

    def __exit__(self,type,value,traceback):
        os.remove(self.imagefile)


def main():

    for i in range(1,len(sys.argv)):
        str,dummy,val = sys.argv[i].partition("=")
        if str == "alarm_id":   idx      = val
        if str == "cam_id"  :   camname  = val
        if str == "cam_port":   camport  = val
        if str == "username":   username = val
        if str == "password":   password = val

    with CamView(camname,camport,idx,username,password) as viewer:

        viewer.show()

        start_time = time.time()
        firstimage = True
        while(time.time() - start_time <= 30):

            viewer.update_image()
            curr_time = round(time.time()-start_time, 0)

            if firstimage:

                firstimage = False
                nowtime = time.strftime("%I:%M %p")

                viewer.image.setAnimations([('conditional', 'effect=fade start=0 end=100 time=750 delay=125 condition=true'),
                                            ('conditional', 'effect=slide start=400,0 end=0,0 time=750 condition=true')])

                xoptions = ("Notification(\"" + viewer.msg + "\", " + nowtime + ", 29500, special://masterprofile/addon_data/" +
                            xbmcaddon.Addon().getAddonInfo('id') + "/" + camname + ".png)")
                xbmc.executebuiltin(xoptions)


            elif curr_time == 30:
                viewer.image.setAnimations([('conditional', 'effect=fade start=100 end=0 time=750 condition=true'),
                                            ('conditional', 'effect=slide start=0,0 end=400,0 time=750 condition=true')])

            else:
                viewer.image.setAnimations([('conditional', 'effect=fade start=100 end=100 time=0 condition=true')])


            xbmc.sleep(500)


if __name__ == "__main__":

    if xbmc.getInfoLabel("Window(10000).Property(foscamScriptRunning)") == "True":
        xbmc.log('Script already running', level=xbmc.LOGERROR)
    else:
        xbmc.log('Foscam alarm triggered', level=xbmc.LOGNOTICE)
        xbmcgui.Window(10000).setProperty("foscamScriptRunning", "True")
        main()
        xbmcgui.Window(10000).setProperty("foscamScriptRunning", "False")

原始脚本使用urllib,我发现它不支持digest 任何方便的身份验证方式。于是我改成了urllib2。这不起作用,因为我的 XBMC 弹出窗口中的图像在第一张图像之后没有更新。有时,甚至根本没有图像。

所以我进行了一些挖掘,我很快发现使用urllib2Digest 身份验证获取快照需要7 秒多一点! (使用旧固件,这需要不到 0.1 秒)。考虑到这可能是图像未更新的原因,我将所有内容都更改为 requests 模块。分析显示,现在从相机获取单个快照大约需要 0.25 秒;恕我直言,仍然相当慢,但也许可以接受。但是,同样使用此方法,通知图像也不会更新。

我正在通过远程 SSH 触发脚本,因此我可以检查 XBMC 日志等。我还检查了 snapshot.jpg 文件创建时的时间戳,它们似乎与脚本触发时间一致,并且requests 的 0.25 秒延迟。在 XBMC 脚本中,我将清除映像并将其设置为新快照的顺序更改为您能想到的所有可能的顺序,但没有成功。如果我在清除和重新设置图像之间设置延迟,我会看到一个闪烁的图像,表明一切正常。但是,它总是被重新设置为完全相同的快照。

所以,我真的很困惑。我在这里俯瞰什么?

【问题讨论】:

  • 有没有机会回滚到以前的固件???除非我们拥有相同的硬件,否则任何人都很难提供帮助.. :((
  • @mlwn 不是真的,相机甚至没有“保存当前固件”选项.....我希望这是 python 代码的问题,或者有人遇到过类似的问题将使用的模块与摘要身份验证相结合...
  • 我对这个主题很感兴趣..并想提供我的帮助。但我从来没有使用过这样的硬件......你认为网上的某个地方可能有一个模拟器吗???我愿意以任何方便的方式提供帮助...

标签: python plugins ip-camera xbmc


【解决方案1】:

为了它的价值:

我最终“修复”了这个问题,将每个单独的快照保存在一个唯一的名称下(基于时间生成的名称,以微秒为单位),然后删除所有这些单独的文件。

这暗示了 xbmcgui.ControlImage.setImage() 的一些缓存问题,但我一直找不到任何提到缓存的文档...

我在使用这种方法时遇到的一个问题是,如果您在显示通知时按Esc(因为在这种情况下,所有 XBMC 控制都将丢失),图像并不总是被正确清理。相对较小的问题,但它清楚地表明这是一个臭的解决方案:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多