Изображение уведомления XBMC (поступающее с IP-камеры) не обновляется

У меня есть коробка XBMC, подключенная к моему телевизору. Кроме того, у меня есть 2 IP-камеры Foscam, которые я использую для наблюдения за двумя моими маленькими девочками.

Некоторое время назад я подумал, что было бы неплохо написать пару скриптов, чтобы при срабатывании одного из сигналов тревоги Foscam я получал уведомление на XBMC вместе с живыми изображениями с соответствующей камеры Foscam. Благодаря этому я мог смотреть телевизор, не спуская глаз с детей.

Итак, на коробке XBMC у меня запущен сценарий оболочки, который каждую секунду проверяет статусы сигналов тревоги 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 никогда не обновлялось после первого изображения. Иногда вообще не было изображения.

Поэтому я немного покопался и быстро обнаружил, что получение моментальных снимков с urllib2 с аутентификацией Digest заняло чуть более 7 секунд! (со старой прошивкой это занимало чуть меньше 0,1 секунды). Думая, что это может быть причиной того, что изображения не обновляются, я изменил все на модуль requests. Профилирование показало, что получение одного снимка с камеры теперь занимает где-то 0,25 секунды; все еще довольно медленно ИМХО, но, возможно, приемлемо. Однако и при использовании этого метода изображения уведомлений не обновляются.

Я запускаю сценарий через удаленный SSH, поэтому я могу проверить журналы XBMC и т. д. Я также проверил временные метки в файлах snapshot.jpg по мере их создания, и они, кажется, согласуются со временем запуска сценария и задержкой 0,25 секунды на requests. В сценарии XBMC я безуспешно изменил порядок очистки изображения и установки нового снимка в любой возможный порядок, который только можно придумать. Если ставлю задержку между очисткой и перенастройкой изображения, то вижу мерцающее изображение, что говорит о том, что все работает. Однако он всегда переустанавливается на один и тот же моментальный снимок.

Итак, я действительно застрял. Что я здесь упускаю?


person Rody Oldenhuis    schedule 16.06.2014    source источник
comment
есть возможность откатиться на предыдущую прошивку??? Кому-то очень сложно помочь, если у нас нет такого же оборудования.. :((   -  person mlwn    schedule 21.07.2014
comment
@mlwn не совсем, у камеры даже нет опции сохранения текущей прошивки ..... Я надеялся, что это проблема с кодом Python, или кто-то сталкивался с подобными проблемами с используемыми модулями в сочетании с дайджест-аутентификацией. ..   -  person Rody Oldenhuis    schedule 21.07.2014
comment
Я заинтересован в этой теме .. и хотел бы предложить свою помощь. Но я никогда не работал с таким железом... как вы думаете, может быть симулятор где-то в сети??? Готов помочь любым удобным способом...   -  person mlwn    schedule 21.07.2014


Ответы (1)


Для чего это стоит:

Я, наконец, «исправил» проблему, сохранив каждый отдельный снимок под уникальным именем (имена, сгенерированные на основе времени с микросекундами), а затем удалив все эти отдельные файлы.

Это указывает на некоторые проблемы с кэшированием в xbmcgui.ControlImage.setImage(), но мне не удалось найти документацию, в которой упоминается кэширование...

Одна проблема, с которой я столкнулся при таком подходе, заключается в том, что если вы нажимаете Esc во время отображения уведомления (потому что в этом случае теряется весь контроль XBMC), изображения не всегда очищаются должным образом. Относительно незначительная проблема, но это явный признак того, что это вонючее решение :)

person Rody Oldenhuis    schedule 22.09.2014