I'm terrible at python and need your help with two questions

  Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Post Reply
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #1
Hey so I have a working script that I'm trying to add two features too. As it turns out I happen to not be picking up python very quick. This is a one-off effort and I'd just like it done. Also I think what I'm looking for would be very simple for someone experienced to answer, versus hours of head scratching for me.

So the prelude to my question is what my script is for. I have a home automation door bell hooked up to notify me when someone rings the doorbell. I then have an ip Camera take some photos of who it is.

When someone rings the bell, this script I wrote gets invoked. The script simply enough grabs the image from the camera and displays it on the screen.

I'm looking for two pieces of functionality:

1) I need to somehow loop sleep every second and essentially refresh the image on the screen. The image location gets refreshed on its own independent of this script. So I just need to keep loading that image and redrawing it on screen to get an animation or "video" from the camera.

2) I somehow need to exit the script after a timeout. As in I want this script to exit on it's own with no user interaction.

So all in all, including the existing functionality the script should behave is follows.

1) Invoke script and display image when someone rings bell (done)
2) Every second refresh that image
3) After 10 seconds exit the script, taking me back to whatever was on screen before, such as video, homescreen, etc.

Could someone please help me, it'd be much appreciated. Thanks.


Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui

class MyScript(xbmcgui.Window):

    def __init__(self):
        
         self.addControl(xbmcgui.ControlImage(100, 0, 1080, 720, "special://masterprofile/media/bell.jpg"))

My_Window = MyScript()
My_Window.doModal()
del My_Window
(This post was last modified: 2014-01-07 04:14 by ronie.)
find quote
Kr0nZ Offline
Member
Posts: 57
Joined: Apr 2011
Reputation: 2
Post: #2
try something like this

Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time

class MyScript(xbmcgui.Window):

    def __init__(self):
        curSeconds = time.time()
        imgControl = xbmcgui.ControlImage(100, 0, 1080, 720, "")
        self.addControl(imgControl)
        while (time.time() - curSeconds <= 10):
            imgControl.setImage("")
            imgControl.setImage("special://masterprofile/media/bell.jpg")
            xbmc.sleep(500)

My_Window = MyScript()
My_Window.doModal()
del My_Window
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #3
(2013-02-18 12:29)Kr0nZ Wrote:  My_Window = MyScript()
My_Window.doModal()
del My_Window[/code]

Hey thanks, I appreciate your help. However this isnt working, it's actually behaving similarly to how I had my script written previously.

The problem here is it doesnt draw the image on screen, sleep, redraw, repeat. It does all of that in the background and then once done the loop draws it on the screen.

In other words when you run the script, nothing visually happens on screen for 10 seconds, and then the image is drawn.

I'm suspecting (guessing) that doModal is what's responsible for drawing the screen. And somehow it needs to loop, sleep, draw repeat. I'm not entirely sure though.

And lastly how do I do question #2 where I get the app to close itself after a timeout?
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #4
OK so I found a way to get this to work, I use show() instead of modal() and I just manually recall it between sleeps. However I think this is rather hackish and I'd like to do this in a more proper way similar to what you had suggested.

However, this way it not only refreshed the image but it also exits the script on it's own.

Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui

class MyScript(xbmcgui.Window):

    def __init__(self):
        self.addControl(xbmcgui.ControlImage(100, 0, 1080, 720, "special://masterprofile/media/bell.jpg"))

My_Window = MyScript()
My_Window.show()
xbmc.sleep(2000)
My_Window.show()
xbmc.sleep(2000)
My_Window.show()
xbmc.sleep(2000)
My_Window.show()
xbmc.sleep(2000)

del My_Window
find quote
Kr0nZ Offline
Member
Posts: 57
Joined: Apr 2011
Reputation: 2
Post: #5
doModal() is suppose to loop until you call self.close(), as far as I understand it, doModal loops and redraws on its own,
Im not sure why it isn't for you. I tested what I gave you and it worked for me.

http://xbmc.sourceforge.net/python-docs/...ow-doModal
http://xbmc.sourceforge.net/python-docs/...indow-show

EDIT:
I just realized what I did wrong in the code I gave you,
Then code should be placed in the onInit() function instead of __init_(),
xbmc doesn't draw the control until after the __init__ function is called

So it should be like this:
Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time

class MyScript(xbmcgui.Window):

    def onInit(self):
        curSeconds = time.time()
        imgControl = xbmcgui.ControlImage(100, 0, 1080, 720, "")
        self.addControl(imgControl)
        while (time.time() - curSeconds <= 10):
            imgControl.setImage("")
            imgControl.setImage("special://masterprofile/media/bell.jpg")
            xbmc.sleep(500)

        self.close()

My_Window = MyScript()
My_Window.doModal()
del My_Window
(This post was last modified: 2013-02-18 21:44 by Kr0nZ.)
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #6
Hmm when I try that all I get is a black screen. I'm running XBMC version 11, what about you?

I did some dabbling on my own and I ended up with this. Seems to work but when I hit escape it just breaks the current iteration of the loop, I want it to kill the script entirely. Even though mine works I wouldn't mind understanding why yours doesnt for me.

Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time

class MyScript(xbmcgui.Window):

    def __init__(self):
        self.addControl(xbmcgui.ControlImage(100, 0, 1080, 720, "special://masterprofile/media/bell.jpg"))    
    
My_Window = MyScript()
curSeconds = time.time()
while (time.time() - curSeconds <= 10):
  My_Window.show()
  xbmc.sleep(500)

del My_Window
find quote
Kr0nZ Offline
Member
Posts: 57
Joined: Apr 2011
Reputation: 2
Post: #7
Not sure why it doesn't work for you, Im also on eden.
I just added this
Code:
curSeconds = time.time()
        imgControl = xbmcgui.ControlImage(100, 0, 1080, 720, "")
        self.addControl(imgControl)
        while (time.time() - curSeconds <= 10):
            imgControl.setImage("")
            imgControl.setImage("special://masterprofile/media/bell.jpg")
            xbmc.sleep(500)

        self.close()
to the onInit functions of one of my other gui addons, and it works..
does your log show any errors?

But anyway if you want to exit out of the script before the 10secs are up, you would need to go about it a different way, the while loop will block until its completed. You need to add an onAction() and listen for one of the "cancel" action IDs, but I not sure how you would then refresh the image.
(This post was last modified: 2013-02-18 22:31 by Kr0nZ.)
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #8
I have a somewhat working copy here. The end goal is to use urlretrieve to fetch new images off my ipcamera, which it appears to be doing. But when I loop through it it's one static image.

Still can't figure out why I cant get it to work your way. I'm not getting any errors in the xbmc logs. If I could just get the image to refresh I'd be set, do I have to clear it first or something?

If I duplicate class MyScript, name it to myscript2 and call them one after another in my loop at the bottom, it does draw two separate images one after another, but when both get run on subsequent loops it doesnt update the images.


Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time, urllib, urllib2, Cookie, xml.etree.ElementTree
#get actioncodes from https://github.com/xbmc/xbmc/blob/master/xbmc/guilib/Key.h
ACTION_PREVIOUS_MENU = 10
ACTION_SELECT_ITEM = 7


class MyScript(xbmcgui.Window):

    def __init__(self):
        urllib.urlretrieve("http://url.com/camera/", '/tmp/bell.jpg')
        self.addControl(xbmcgui.ControlImage(100, 0, 1080, 720, "/tmp/bell.jpg"))
        
My_Window = MyScript()
curSeconds = time.time()
while (time.time() - curSeconds <= 10):
  My_Window.show()
  xbmc.sleep(1000)
  
del My_Window
(This post was last modified: 2013-02-18 23:35 by doobiest.)
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 17
Post: #9
I think this should do it:
Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time

#inherit from WindowDialog instead of Window so that it's shown on top of
#what's onscreen instead of replacing it entirely
class CamView(xbmcgui.WindowDialog):

    def __init__(self):
        #set the initial image before the window is shown
        self.image = xbmcgui.ControlImage(100, 0, 1080, 720, "special://masterprofile/media/bell.jpg")
        self.addControl(self.image)


viewer = CamView()
viewer.show()
start_time = time.time()
while(time.time() - start_time <= 10):
    viewer.image.setImage("special://masterprofile/media/bell.jpg")
    xbmc.sleep(500)
viewer.close()
del viewer
find quote
ronie Offline
Team-Kodi Member
Posts: 13,045
Joined: Jan 2009
Reputation: 375
Post: #10
since the filename of your image is static, xbmc won't pick up the new image when it changes.

to address this (as mentioned in one of the examples above), you need to use imgControl.setImage("") in the loop.
...and you may even have to set some sleep time between clearing and setting the image.

Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ and Search the forum before posting.
For troubleshooting and bug reporting please make sure you read this first.
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #11
Hey thanks that seems to work well, however it's still not refreshing the image that im downloading with urlretrieve. I've included two changes.

Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, time, urllib

#inherit from WindowDialog instead of Window so that it's shown on top of
#what's onscreen instead of replacing it entirely
class CamView(xbmcgui.WindowDialog):

    def __init__(self):
        #set the initial image before the window is shown
        #NEW
        urllib.urlretrieve("http://sdf.com/camera/", '/tmp/bell.jpg')
        self.image = xbmcgui.ControlImage(100, 0, 1080, 720, "/tmp/bell.jpg")
        self.addControl(self.image)


viewer = CamView()
viewer.show()
start_time = time.time()
while(time.time() - start_time <= 10):
    #NEW
    urllib.urlretrieve("http://sdf.com/camera/", '/tmp/bell.jpg')
    viewer.image.setImage("/tmp/bell.jpg")
    xbmc.sleep(500)
viewer.close()
del viewer

(2013-02-19 00:53)ronie Wrote:  since the filename of your image is static, xbmc won't pick up the new image when it changes.

to address this (as mentioned in one of the examples above), you need to use imgControl.setImage("") in the loop.
...and you may even have to set some sleep time between clearing and setting the image.

Thanks I was wondering about that. That actually fixed a big part of the problem.

(2013-02-19 00:38)Bstrdsmkr Wrote:  #inherit from WindowDialog instead of Window so that it's shown on top of
#what's onscreen instead of replacing it entirely
class CamView(xbmcgui.WindowDialog):

Can you tell me if it's possible to set the transparency of this? I'd like any video playing to be somewhat viewable.

Also I have 4 instances of xbmc running that I'm testing against, 2 windows, 2 linux and all of them seem to crash upon completion of this script at various times. Could there be anything specific or is it just flakey?
(This post was last modified: 2013-02-19 00:59 by doobiest.)
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 17
Post: #12
Sounds like the image is being cached. Try adding a bogus parameter to the url like:
Code:
url = "http://sdf.com/camera/?bogus=%s" %time.time()
urllib.urlretrieve(url, '/tmp/bell.jpg')
The camera's server should ignore the extra param (try it in your browser to be sure) and xbmc will see a different url each time and won't return a cached image.

The other possibility is that it's showing a cached thumbnail of /tmp/bell.jpg. In that case, you'll need to change the location passed in to setImage() call. You can do this by saving each image separately:
Code:
# Import the XBMC/XBMCGUI modules.
import xbmc, xbmcgui, urllib

#inherit from WindowDialog instead of Window so that it's shown on top of
#what's onscreen instead of replacing it entirely
class CamView(xbmcgui.WindowDialog):

    def __init__(self):
        #set the initial image before the window is shown
        urllib.urlretrieve("http://sdf.com/camera/", '/tmp/bell.jpg')
        self.image = xbmcgui.ControlImage(100, 0, 1080, 720, "/tmp/bell.jpg")
        self.addControl(self.image)


viewer = CamView()
viewer.show()

count = 1
while(count < 10):
    #NEW
    location = '/tmp/bell%s.jpg' %count
    urllib.urlretrieve("http://sdf.com/camera/", location)
    viewer.image.setImage(location)
    xbmc.sleep(1000)
viewer.close()
del viewer

The drawback is this will always show 10 images, regardless of how long it takes. It shouldn't normally matter, but it's something to keep in mind
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #13
Thanks,

I'm going to try this new code when I get off work tomorrow. In the meant time, what everyone has provided me has been a big help and I have the basic functionality that I need to use it in practice until I improve upon it.

If you're interested I posted some screenshots on my blog. I'm very pleased!

http://homeawesomation.wordpress.com/201...mc-update/
(This post was last modified: 2013-02-19 02:42 by doobiest.)
find quote
Bstrdsmkr Offline
Posting Freak
Posts: 802
Joined: Oct 2010
Reputation: 17
Post: #14
I could swear Ronie's post wasn't there when I replied lol

AFAIK, you can't set the transparency directly. You'd need to edit the image first. You could do so using PIL, but it's probably not worth the extra time it would take. You can also just set the size of the image control smaller than the image actually is, maybe show it in the corner like PIP?

If you post a log from the crash we can probably get it dialed in
find quote
doobiest Offline
Junior Member
Posts: 49
Joined: May 2005
Reputation: 0
Post: #15
Check my link you'll see that is PIP Smile

So I've deployed this to all of my XBMC instances. But on my one downstairs it's complaining about writing to /tmp. To be clear I have this running as is fine on another win7 box, and the one it's failing on is win7

I originally had tried writing the image to special:/profile/something but according to google urlretrieve doesn't like colons in it's path. Which makes me wondering how people develop on windows using this library. Am I just not escaping it properly? And also find it very odd that is doesnt work on just that one box.

Code:
21:00:25 T:2628  NOTICE: -->Python Interpreter Initialized<--
21:00:25 T:2628   ERROR: Error Type: <type 'exceptions.IOError'>
21:00:25 T:2628   ERROR: Error Contents: (2, 'No such file or directory', '/tmp/bell.jpg')
21:00:25 T:2628   ERROR: Traceback (most recent call last):
                                              File "C:\Users\rich\AppData\Roaming\XBMC\addons\script.doorbell\doorbell.py", line 18, in <module>
                                                viewer = CamView()
                                              File "C:\Users\rich\AppData\Roaming\XBMC\addons\script.doorbell\doorbell.py", line 10, in __init__
                                                urllib.urlretrieve("http://wwwerd.com/camera/", '/tmp/bell.jpg')
                                              File "C:\Program Files\XBMC\system\python\Lib\urllib.py", line 93, in urlretrieve
                                                return _urlopener.retrieve(url, filename, reporthook, data)
                                              File "C:\Program Files\XBMC\system\python\Lib\urllib.py", line 243, in retrieve
                                                tfp = open(filename, 'wb')
                                            IOError: (2, 'No such file or directory', '/tmp/bell.jpg')


EDIT: I figured it out. It's just by coincidence that it worked on my other windows 7 box. I already had a folder of c:\tmp created with proper permissions for a completely unrelated reason. I only had to create that folder on the other computer for it to work. Ideally I should have it going to a path that isn't dependent on manual creation. Others I had tried it failed with write perms. What is the proper path to temp files for a script?
(This post was last modified: 2013-02-19 04:28 by doobiest.)
find quote
Post Reply