Изображение уведомления XBMC (с IP-камеры) не обновляется
У меня есть коробка XBMC, подключенная к моему телевизору. Кроме того, у меня есть две 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 я изменил порядок очистки изображения и присвоил ему новый снимок для каждого возможного порядка, который вы можете придумать, но безуспешно. Если я поставлю задержку между очисткой и переустановкой изображения, я вижу мерцающее изображение, предполагая, что все это работает. Тем не менее, он всегда сбрасывается на один и тот же снимок.
Итак, я действительно застрял. Что я здесь пропускаю?
1 ответ
Для чего это стоит:
Наконец, я "исправил" проблему, сохранив каждый отдельный снимок под уникальным именем (имена, созданные на основе времени с микросекундами), а затем удалил все эти отдельные файлы.
Это указывает на некоторые проблемы с кэшированием xbmcgui.ControlImage.setImage()
, но я не смог найти никакой документации, упоминающей кеширование...
Одна проблема, с которой я столкнулся при таком подходе, заключается в том, что если нажать Esc
пока отображается уведомление (потому что в этом случае теряется весь контроль XBMC), это то, что изображения не всегда очищаются должным образом. Относительно небольшая проблема, но это явный признак того, что это вонючее решение:)