Author Topic: Gmail notifier - Using IP camera email notifications to trigger events in VC  (Read 30660 times)

0 Members and 2 Guests are viewing this topic.

nime5ter

  • Administrator
  • Hero Member
  • *****
  • Posts: 1999
  • Karma: 61
    • View Profile
    • Getting Started with VoxCommando
OK. The revised code is attached.

You will have to replace the sender email address in the script with your babycam address, of course.

I have provided 2 different options.

Option 1 -- If you use the code in its current form, then:

1. Any time you receive a message from the camera, VC will generate an event babyCam.[subject line]

2. If the email contains a message body, you can access it as payload {1}. [see image babycam]

I think the above solution will be the easiest, but if you have very long subject lines or you can't control what they say, then maybe you won't like it.

Option 2 is actually what we discussed earlier today [see image babycam_option2]. In this case:

1. Any time you receive a message from the camera, VC will generate an event babyCam.
2. The email subject line will be stored as payload {1} and if there is also a message it will be stored as payload {2}.

In this case, you will have to be more creative in VC to evaluate {1} and then decide what happens.

There are instructions in the python script for how to use Option 2 instead of Option 1. (Basically, you delete the currently active "VC.TriggerEvent" line of code or insert a # in front so that it is not readable, and instead use the line that is directly under it.)

Enjoy. Let me know if you have any questions.
« Last Edit: February 19, 2015, 05:23:34 PM by nime5ter »
TIPS: POST VC VERSION #. Explain what you want VC to do. Say what you've tried & what happened, or post a video demo. Attach VC log. Link to instructions followed.  Post your command (xml)

Mirac78

  • Jr. Member
  • **
  • Posts: 49
  • Karma: 5
    • View Profile
    • M.S.Photography
It's working! :-D

I'm using option one. I had some problems to create event, not sure but in script i rename all  "gmail_notifier.py" with "BabyCam_gmail_notifier.py"..

I'm so happy  ;D ;D

nime5ter

  • Administrator
  • Hero Member
  • *****
  • Posts: 1999
  • Karma: 61
    • View Profile
    • Getting Started with VoxCommando
I'm not sure what you mean by "in script" but, yes, you need to load the python script using a VC command. That command should refer to the file name of the script.

So, either you need to rename the python file "gmail_notifier.py" or you need to change the VC command you are using to load the script so that it refers to the correct file.

But you should only have needed to change that in one command, right?

You only need to load your python file once, when your first start VoxCommando. It will continue to run as long as you have VC open.

e.g.
Code: [Select]
<?xml version="1.0" encoding="utf-16"?>
<!--VoxCommando 2.1.3.8-->
<commandGroup open="True" name="Babycam" enabled="True" prefix="" priority="0" requiredProcess="" description="">
  <command id="161" name="load python code when VC launches" enabled="true" alwaysOn="False" confirm="False" requiredConfidence="0" loop="False" loopDelay="0" loopMax="0" description="">
    <action>
      <cmdType>PY.ExecFile</cmdType>
      <params>
        <param>PY\BabyCam_gmail_notifier.py</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <event>VC.Loaded</event>
  </command>
  <command id="162" name="Baby is moving" enabled="true" alwaysOn="False" confirm="False" requiredConfidence="0" loop="False" loopDelay="0" loopMax="0" description="">
    <action>
      <cmdType>OSD.ShowText</cmdType>
      <params>
        <param>Baby says:</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <action>
      <cmdType>OSD.AddText</cmdType>
      <params>
        <param>Wa WAH wa WAH</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <event>babyCam.motion</event>
  </command>
</commandGroup>
TIPS: POST VC VERSION #. Explain what you want VC to do. Say what you've tried & what happened, or post a video demo. Attach VC log. Link to instructions followed.  Post your command (xml)

Mirac78

  • Jr. Member
  • **
  • Posts: 49
  • Karma: 5
    • View Profile
    • M.S.Photography
All clear and all set it up. Add a few logic rules and that's it. Script loaded only once, only need to find some good ping time.

Check your PM..

M.


mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
Hi Nime5ter,

One question: (i am a very new to VC)
i checked your XML from the first post, and the action (show text) is triggered IF the
message {2} is NOT empty.
so far so good :)

is there is a way to nest IF-THEN logic ?
e.g.
if {2} is NOT empty

  if {2} = "Hello, message 1"
    osd.showtext "this is message 1"
  endif

  if {2} = "Hello, message 2"
    osd.showtext "and this is message 2"
  endif

endif

in this way, you do the comparison only AND only if {2} is NOT empty
this is only a example, but i can implement it in another projects

the best could be have a switch-case instructions, but i dont know if VC have it

thank you very much

PegLegTV

  • $upporter
  • Sr. Member
  • *****
  • Posts: 497
  • Karma: 43
    • View Profile

One question: (i am a very new to VC)
i checked your XML from the first post, and the action (show text) is triggered IF the
message {2} is NOT empty.
so far so good :)

is there is a way to nest IF-THEN logic ?



this is a simple example of a nested IF as you described in your question,

Code: [Select]
<?xml version="1.0" encoding="utf-16"?>
<!--VoxCommando 2.2.0.9-->
<command id="1104" name="Simple nested IF" enabled="true" alwaysOn="False" confirm="False" requiredConfidence="0" loop="False" loopDelay="0" loopMax="0" description="when using &quot;Test payload VALUES&quot; make sure you add something to {1} so {2} works ">
  <action>
    <cmdType>Results.RegEx</cmdType>
    <params>
      <param>(\{2\})</param>
      <param />
      <param>{2}</param>
    </params>
    <cmdRepeat>1</cmdRepeat>
  </action>
  <if ifBlockDisabled="False" ifNot="False">
    <ifType>LastActionSuccess</ifType>
    <ifParams>&amp;&amp;</ifParams>
    <then>
      <action>
        <cmdType>OSD.ShowText</cmdType>
        <params>
          <param>payload 2 is empty (if 1)</param>
        </params>
        <cmdRepeat>1</cmdRepeat>
      </action>
      <action>
        <cmdType>VC.StopMacro</cmdType>
        <params />
        <cmdRepeat>1</cmdRepeat>
      </action>
    </then>
    <else>
      <action>
        <cmdType>OSD.ShowText</cmdType>
        <params>
          <param>payload 2 is not empty (else 1)</param>
        </params>
        <cmdRepeat>1</cmdRepeat>
      </action>
    </else>
  </if>
  <if ifBlockDisabled="False" ifNot="False">
    <ifType>(A)==(B)</ifType>
    <ifParams>{2}&amp;&amp;Hello 1</ifParams>
    <then>
      <action>
        <cmdType>OSD.AddText</cmdType>
        <params>
          <param>{2} (if 2)</param>
        </params>
        <cmdRepeat>1</cmdRepeat>
      </action>
      <action>
        <cmdType>VC.StopMacro</cmdType>
        <params />
        <cmdRepeat>1</cmdRepeat>
      </action>
    </then>
    <else />
  </if>
  <if ifBlockDisabled="False" ifNot="False">
    <ifType>(A)==(B)</ifType>
    <ifParams>{2}&amp;&amp;Hello 2</ifParams>
    <then>
      <action>
        <cmdType>OSD.AddText</cmdType>
        <params>
          <param>{2} (if 3)</param>
        </params>
        <cmdRepeat>1</cmdRepeat>
      </action>
    </then>
    <else />
  </if>
</command>

you will notice in mine I'm using Regex to figure out if {2} is empty, I'm doing this because the method that you refer to doesn't seem to work for me, but using Results.RegEx did

Hello 1 will trigger the second if statement

Hello 2 will trigger the third if statement

NOTE: in the command editor, when testing payloads under "Test payload VALUES" make sure that you add something to {1} otherwise {2} will be seen as empty

mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
Thank you PegLegTV,

I will check it in detail, the first question that comes to my mind:

Where or how are you checking that {1} payload is empty or not ?

thanks again for your help, it is not what i have in mind (switch-case) but it could work for my needs


jitterjames

  • Administrator
  • Hero Member
  • *****
  • Posts: 7714
  • Karma: 116
    • View Profile
    • VoxCommando
If your command might be triggered with a variable number of payloads then the best way to handle that is usually to use {#P}

see: http://voxcommando.com/mediawiki/index.php?title=Logical_Command_Builder#Using_Payloads_and_other_variables_with_.7B_.7D

There are different reasons why you might have a variable number of payloads.  Usually in a voice command this will only happen if you have marked one or more of your payloads as "optional".  I would recommend that you avoid doing this unless you really need to and you know what you are doing.  That said, it can be useful. 

One thing that is important to note is that there is a big difference between a payload being blank (as in a string "" - with no characters), and a payload not being there at all.

In the case of optional payloads in your voice command the payload may not be there at all.  If the first payload in your voice command is marked as optional and the user does not say it, and you have a second payload in your voice command, the macro will only see a single payload (the second one in your command) and it will be accessible as {1}, not {2}.

An event on the other hand may trigger a command and the event can contain payloads that use empty strings, so that the first payload might be "".  In that case you could evaluate {1} to see if it is equal to ""
« Last Edit: December 27, 2015, 12:00:43 PM by jitterjames »

jitterjames

  • Administrator
  • Hero Member
  • *****
  • Posts: 7714
  • Karma: 116
    • View Profile
    • VoxCommando

...

is there is a way to nest IF-THEN logic ?

...

the best could be have a switch-case instructions, but i dont know if VC have it

VC macros cannot do nested Ifs.  For advanced logic you must either use Python or do a workaround with VC.StopMacro as Pegleg has shown or devise some other kind of work-around.

There is no switch / case either.  Again you can either use Python or VC.StopMacro.

It is conceivable that a switch block might be added in a future version ( ::dis no promises) but it's highly unlikely that we will ever add support for nested Ifs because the programming and design of the UI would require major changes.  Since we have alternatives that work well enough for the rare situations where we need it, I would rather spend that time working on the 100+ other things that need development at any given point in time.

mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
Thank you James for the explanation, it was very informative also.

Is there a maximum number of if - then that can be used ?

I installed the .py and xml from the first post.. Gmail notifier
Everything works well, except that after 10 minutes or so
VC crashed and Windows close it, and ask me for find an online solution

I know is this script, because I disable that group an VC
Worked fine

VC Ver 2209
Problem in both version of Windows 7 and 10

Any help ?

Thanks

jitterjames

  • Administrator
  • Hero Member
  • *****
  • Posts: 7714
  • Karma: 116
    • View Profile
    • VoxCommando
Any help ?

Maybe we can try to help if you send us a complete log.

You should also provide a link to let us know exactly which python script you are using, or better yet, attach the script you are using.

Otherwise we would just be guessing.

mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
Thanks, here is the code :

Code: [Select]
<?xml version="1.0" encoding="utf-16"?>
<!--VoxCommando 2.2.0.7-->
<commandGroup open="True" name="Gmail notifier alert" enabled="False" prefix="" priority="0" requiredProcess="" description="">
  <command id="272" name="Alert received" enabled="true" alwaysOn="False" confirm="False" requiredConfidence="0" loop="False" loopDelay="0" loopMax="0" description="">
    <action>
      <cmdType>OSD.ShowText</cmdType>
      <params>
        <param>Alert received.</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <action>
      <cmdType>OSD.AddText</cmdType>
      <params>
        <param>Subject: {1}</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <if ifBlockDisabled="False" ifNot="True">
      <ifType>(A)==(B)</ifType>
      <ifParams>{2}&amp;&amp;</ifParams>
      <then>
        <action>
          <cmdType>TTS.Speak</cmdType>
          <params>
            <param>Subject. {1} . Message. {2}</param>
          </params>
          <cmdRepeat>1</cmdRepeat>
        </action>
        <action>
          <cmdType>OSD.AddText</cmdType>
          <params>
            <param>Message: {2}</param>
          </params>
          <cmdRepeat>1</cmdRepeat>
        </action>
      </then>
      <else />
    </if>
    <event>newMsgVC</event>
  </command>
  <command id="358" name="Gmail Startup" enabled="true" alwaysOn="False" confirm="False" requiredConfidence="0" loop="False" loopDelay="0" loopMax="0" description="">
    <action>
      <cmdType>PY.ExecFile</cmdType>
      <params>
        <param>PY\GmailStartup.py</param>
      </params>
      <cmdRepeat>1</cmdRepeat>
    </action>
    <event>VC.Loaded</event>
  </command>
</commandGroup>
« Last Edit: December 27, 2015, 05:05:54 PM by Kalle »

mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
I am sorry, but i don't find a way to attach the XML other than copy-paste
in the body of the post

mexicanto

  • Contributor
  • ***
  • Posts: 55
  • Karma: 1
    • View Profile
This is the .PY script (i uploaded before, but i forgot to erase my user name and password)

Code: [Select]
import urllib2, re, time, thread, traceback
from System.Collections.Generic import *
ATOM_URL='https://mail.google.com/mail/feed/atom'
gusr="daniel.gaitan.carrillo"
gpwd="********"#Disclaimer: Anyone who reads this python file can see this.

class mailChecker:

    def __init__(self, uName,pwd):
        self.username = uName
        self.password = pwd
        self.fullCount = "0"#I don't use message count as a condition in this script, but one could
        self.msgID = "dummy"
        self.timestamp = round(time.clock())
        vc.log("gmail_notifier.py - mailChecker initialized")     
           
    def get_feed(self,user, passwd):
        auth_handler = urllib2.HTTPBasicAuthHandler()
        auth_handler.add_password(realm='mail.google.com',uri='https://mail.google.com',user='{user}@gmail.com'.format(user=user),passwd=passwd)
        opener = urllib2.build_opener(auth_handler)
        urllib2.install_opener(opener)
        feed = urllib2.urlopen(ATOM_URL)
        message_text=feed.read()
       
        try:
            message_text=message_text.decode('utf-8')#try to deal with most non-Latin characters
           
        except:
            pass
       
        return message_text
               
    def readMail(self):
        timeNow = round(time.clock())
        feedData=self.get_feed(self.username, self.password)
        matchObj = re.search( r"fullcount>(\d*)<.*?title>(.*?)<.*?<summary>(.*?)</summary>.*?message_id=(.*?)&amp.*?email>(.*?)<", feedData, re.I)
       
        if matchObj:#if the match object was successfully created, then store matches as variables
       
            if self.msgID == "dummy" and timeNow-self.timestamp<10:
                self.msgID = matchObj.group(4)
                vc.log("GmailStartup.py - setting msgID to existing unread msg on 1st launch")
       
            elif matchObj.group(4)==self.msgID:
                pass#vc.log("GmailStartup.py - no new messages")
       
               
            else:   
                self.fullCount = matchObj.group(1)
                subject = matchObj.group(2)
                summary = matchObj.group(3)
                self.msgID = matchObj.group(4)
                sender = matchObj.group(5)
               
                if subject.lower()=="vc".lower():
                    vc.triggerEvent("newMsgVC", List[str]([subject,summary]))
                    vc.log("GmailStartup.py - condition matched, triggering newMsg event") 
                   
                else:
                    vc.log("No match. Message was: "+subject+"from "+sender)
                                   
        #else: -->not needed except if you're debugging/problem-hunting
            #vc.log("GmailStartup.py - no unread messages")
       
def checkMsg(delay):   

    while 1:
        try:
            myMailChecker.readMail()
            time.sleep(delay)
       
        except:
            error = traceback.format_exc().splitlines()
            vc.log("%s"%error[-1])
           
           

myMailChecker = mailChecker(gusr,gpwd)
thread.start_new_thread(checkMsg, (30,))# checks mail every 30 seconds. Change to your preference.





--- the only thing i made was to change the name of the file to "GmailStartup.py"
« Last Edit: December 27, 2015, 05:07:40 PM by Kalle »

nime5ter

  • Administrator
  • Hero Member
  • *****
  • Posts: 1999
  • Karma: 61
    • View Profile
    • Getting Started with VoxCommando
I am sorry, but i don't find a way to attach the XML other than copy-paste
in the body of the post..

Above the message field are a bunch of buttons that allow you to insert various format tags in your message. The button with the # symbol creates a code block.

Code: [Select]
This is a code block.
Post code in a code block, or attach a file to the post by clicking the "Attachments and other options" link below the message box, and choosing a file to attach to your post
« Last Edit: December 27, 2015, 04:41:46 PM by nime5ter »
TIPS: POST VC VERSION #. Explain what you want VC to do. Say what you've tried & what happened, or post a video demo. Attach VC log. Link to instructions followed.  Post your command (xml)