How can I fix my Apple Script to prevent it from timing out

I am a new to apple script and am not sure how to fix this problem. Basically my script is a countdown timer that sends a message to my phone after the timer has ended. After the timer ends, the message is sent, and a dialog box waits for the user to enter the amount of time to set for the next timer.


I have noticed that when I am not connected to a power source the script times out if I don't enter something into the dialog box. I would like to fix this behavior so that it doesn't time out unless it has been 7 or more hours.


a) how can i do this?

b) is it safe to do this?

-------------------------------------------------------------------------------- ----------------------------------------------------

#Simple Times

#Contdown timer that can be used as a pomodoro timer

#Also able to send break notifications as a text to your phone

on get_txt_preference()


display alert "Send session information to phone?" buttons {"No", "Yes"}

if button returned of result = "yes" then

return true

else

return false

end if

end get_txt_preference


##########################################

#Globals

##########################################

set thePhoneNumber to "+X(XXX)XXX-XXXX" #change to your phone number

set shortBreak to 240 #4 m

set medBreak to 900 #15 m

set longBreak to 3600 #1 hour

set pomodoroVal to 1500 #25 m

set pomoSymbol to "
"

set sendTxtIsOn to get_txt_preference()

set dialogText to ((current date) as string) & "


_________________________________________

_________________________________________

[time] [m || s || h] 25 m, 3 s, 1 h

[minutes] 25

Minutes ||||| Seconds

25 1500

15 900

4 240

_________________________________________

_________________________________________


q to quit


"

global sendTxtIsOn

global shortBreak

global medBreak

global longBreak

global pomodoroVal

global currentPomo

global totalPomo

global pomoSymbol

global dialogText

global thePhoneNumber


###############################

#Functions

##########################################

on quit


display alert "Exit Simple Times?" buttons {"No", "Yes"}

if button returned of result = "yes" then

try


send_txt("Nice work. Pomodoros: " & totalPomo & "

" & "min: " & sec / 60 & "

" & "hour: " & (sec / 60) / 60)

end try

continue quit

end if

end quit


on increment_pomo(theString)

return theString & pomoSymbol

end increment_pomo


on make_pomo_summary(sec, mark)

set summary to (mark & "

" & "min: " & sec / 60) & "

" & "hour: " & ((sec / 60 / 60))

return summary

end make_pomo_summary


on make_break_summary()

set summary to "End of Break" & "

total: " & totalPomo & "

current: " & currentPomo

return summary

end make_break_summary


on send_txt(txt)

if sendTxtIsOn then

tell application "Messages" to activate

tell application "Messages"


sendtxttobuddythePhoneNumber of service "SMS"

end tell

end if

end send_txt


on is_number(x)

try


x as number

return true

on error

return false

end try

end is_number


on is_break(theTime)

return theTime = shortBreak or theTime = medBreak or theTime = longBreak

end is_break


on get_input()

with timeout of (60 * 420) seconds# 7 hour timeout


repeat while true

tell me


activate

set input to text returned of (display dialogdialogTextdefault answer "q")

set n to word 1 of input

end tell

set wordCount to count of (words of input)

if 1 ≤ wordCount and wordCount ≤ 2 and is_number(n) then

if wordCount = 1 then

set modifier to "m"

else

set modifier to character 1 of (word 2 of input)

end if

if modifier = "m" then

return n * 60 as number

else if modifier = "s" then

return n as number

else if modifier = "h" then

return n * 60 * 60 as number

end if

else if n = "q" then


quit

end if

end repeat

end timeout


end get_input


on main()

set totalPomo to ""

set currentPomo to ""

set sec to 0.0

repeat while true

set input to get_input()

repeat input times


delay 1

end repeat


say "times up"

if input = pomodoroVal then

set sec to sec + input

set currentPomo to increment_pomo(currentPomo)

set totalPomo to increment_pomo(totalPomo)

set dialogText to increment_pomo(dialogText)


send_txt(make_pomo_summary(sec, currentPomo))

if length of currentPomo = 4 then

set currentPomo to ""

set totalPomo to totalPomo & " "

set dialogText to dialogText & " "

end if

else if is_break(input) then


send_txt(make_break_summary())

end if

end repeat

end main


main()

--> Result: {button returned:"OK"}

MacBook (Retina, 12-inch, Early 2015), macOS Sierra (10.12.3), null

Posted on Mar 25, 2017 7:29 PM

Reply
8 replies

Mar 28, 2017 1:25 PM in response to tboneshouse

Ah, finally found the real problem (lets hope)

It actually was the fact that I did not handle the case where a message is unable to be sent. So after 120 seconds of trying to send the message, the script times out.


set targetBuddyEmail to "tbones_sauce@me.com"

set message to "Tbone is homeless"


try

with timeout of 10seconds

tell application "Messages"


sendmessagetobuddytargetBuddyEmail of (service 1 whose service type is iMessage)

end tell

end timeout

on error number -1712


display dialog "Sorry Message Couldn't Be sent"

end try



Mar 28, 2017 11:34 AM in response to tboneshouse

Thank you everyone for your help. I think I was able to solve the problem thanks to you all.

Recall that I was confused as to why the sript timed out after a period of inactivity. As some posters have suggested, the problem lied in failing to input anything into the dialog boxes for an extended period of time.

Display dialog, await user input how to get no timeout?

^^ shows how you can avoid time out caused by no input to dialog boxex, namely,

by giving up after x amount of seconds.


As a small example, the script below gives up after 4 seconds of inactivity. If the user clicks a button before the timeout period, then the error is avoided.


set dialogText to ((current date) as string)

global dialogText


on get_input()

tell me


activate

set returned_value to (display dialogdialogTextdefault answer "q" giving up after 4)


--> {button returned:"", text returned:"q", gave up:true}

if gave up of returned_value then

error "i give up"

end if

set input to text returned of returned_value


display dialoginput

end tell

end get_input

get_input()

#####End of Code

Mar 27, 2017 11:01 PM in response to tboneshouse

That's a long, complicated script, and it's not clear which part, precisely, you want to change, but there are two general approaches to avoiding timeouts.


The first is to wrap your code in a 'with timeout of...' statement.

By default, AppleScript waits a certain time (30 second? 60 second? I forget off-hand) for any given statement to complete, before it assumes failure. This is because many AppleScript commands are sent to an application for execution and AppleScript has little or no idea about whether that app is functioning.


The 'with timeout of...' statement tells AppleScript to wait longer (or shorter) for a statement to execute before giving up:


with timeout of 1* hours

tell application "blah" to doSomethingThatTakesALongTime()

end timeout


From your description, though, it sounds like your concern is if the user doesn't enter anything into the display dialog, is that correct? If that's the case have you tried it's 'giving up after' parameter?


display dialog "blah" giving up after 1 * hours

Off hand I don't know if this overrides AppleScripts default timeout, but it's worth trying.


Hopefully some combination of these two pointers will get you moving.

Mar 26, 2017 11:58 AM in response to tboneshouse

(* 

It is easier to diagnose problems with debug information. I suggest adding 
log statements to your script to see what is going on.  Here is an example.


    Author: rccharles
    
    For testing, run in the Script Editor.
      1) Click on the Event Log tab to see the output from the log 
          statement
      2) Click on Run
      
  For running shell commands see:
  http://developer.apple.com/mac/library/technotes/tn2002/tn2065.html
    


 *)


on run
    -- Write a message into the event log.
    log "  --- Starting on " & ((current date) as string) & " --- "
    --  debug lines
    set desktopPath to (path to desktop) as string
    log "desktopPath = " & desktopPath
    
    set unixDesktopPath to POSIX path of desktopPath
    log "unixDesktopPath = " & unixDesktopPath
    
    set quotedUnixDesktopPath to quoted form of unixDesktopPath
    log "quoted form is " & quotedUnixDesktopPath
    
    try
        set fromUnix to do shell script "ls -l  " & quotedUnixDesktopPath
        display dialog "ls -l of " & quotedUnixDesktopPath & return & fromUnix
    on error errMsg
        log "ls -l error..." & errMsg
    end try
    
end run

Mar 26, 2017 3:59 PM in response to rccharles

I have not examined you code carefully. You may be going in the wrong direction.


Here is how a second applescript app can call the first applescript and change a value in the app. Thus you can have an independent applescript set the time to delay. Thus you can leave your first app running and not have to stop to ask a question periodically. [ a.pp ]


on run
    set myApp to "/Applications/applescriptFiles/b.app"
    -- some hocus pocus is nesessary to avoid applescript from change path.
    -- set myApp to POSIX file myApp
   
    tell application myApp
       
        launch
        stringSet("stringie set")
    end tell
end run



This is the applescript file called. There is some hocus pocus here the I'm only vague familiar with now. You need to save as an app. You need to edit the app bundle so to become a full fledged macos app. Hope the link explains. [ b.app ]


(*

save this as an application bundle

invoked by a.app. 

twtwtw write in:
https://discussions.apple.com/thread/4917321?start=15&tstart=0

hocus-pocus:

Give your script application a unique bundle id string (CFBundleIdentifier) and a unique bundle name (CFBundleName) too, to make life easier.  You set those in the info.plist file.  Launch the script app once to register it with launch services, and system will be able to find it thereafter.

Example:
      <key>CFBundleIdentifier</key>
      <string>com.rccharles.b</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>b</string>
   
    I added the CFBundleIdentifier info above the CFBundleInfoDictionaryVersion line. I left the CFBundleInfoDictionaryVersion and CFBundleName as is.
   
    *)

property myVar : "initial value"

on run
    display dialog myVar
end run

on stringSet(inputVar)
    set myVar to inputVar
    display dialog "myVar is " & myVar
end stringSet

Mar 26, 2017 10:27 PM in response to Camelot

That's why I suggest two applescripts. One to handle the timing and the other one to set a time out value. Doesn't exactly meet the requirement to set a new timeout value after a timeout has expired, but ... The poster could incorporate some query facility in the the second applescript so to display the time remaining and whether or not to change the value. Could have the second script set up the next time value after the current one expires.


Just a thought.


R

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

How can I fix my Apple Script to prevent it from timing out

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.