Apple’s Worldwide Developers Conference to kick off June 10 at 10 a.m. PDT with Keynote address

The Keynote will be available to stream on apple.com, the Apple Developer app, the Apple TV app, and the Apple YouTube channel. On-demand playback will be available after the conclusion of the stream.

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Write on Serial port with Applescript

Hey i'd like to print out a message on a specific serial port if i got a new email or not. I use serialport X for this but i always get a syntax error with this script:


set use_port to "/dev/cu.usbmodemfa131"
if (get serialport list) contains use_port then
          set onMode to true
          set myPort to serialport open use_port bps rate 9600 data bits 8 parity 0 stop bits 1 handshake 0
          serialport close use_port
          repeat while onMode is true

tell application "Mail"
          set x to unread count of inbox
          check for new mail
          delay 3
          set y to unread count of inbox
end tell

if x = y then
          serialport write "N"
else
          serialport write "M"
end if
end repeat


Do you have an idea why this always gives me a syntax error ? I am not very good at Applescript 🙂

Thanks

Mac OS X (10.7.4)

Posted on Jul 15, 2012 3:42 PM

Reply
6 replies

Jul 15, 2012 4:05 PM in response to dehlen

I get that the script will now compile with the additional 'end if', but there are still major flaws in your script that will prevent it working.


For example your script opens the port:


          set myPort to serialport open use_port bps rate 9600 data bits 8 parity 0 stop bits 1 handshake 0

and then immediately closes it on the next line:


          serialport close use_port


therefore you won't be able to write any data to it.


Additionally, after you (erroneously) close the port, you then start a repeat loop:


          repeat while onMode is true

However, nowhere within the loop do you change the value of onMode, therefore it will ALWAYS be true and the loop will never exit.


Next, I question the logic of what you're trying to ascertain - you check the number of unread messages, wait three seconds, then check again. In essence you're checking if any new mail comes in within that 3 second period... is that right? It may be.. just seems odd to me.


Finally, for now, when you do come to write data to the port, you say:


          serialport write "N"

I don't know which serialport command you're using, but I would at least expect this to require some idea of the serial port to write to - as it is you're just saying 'write "N"', but you could, legitimately, have multiple serial ports connected to your machine.


Taking the above into consideration, I'd expect your script to look a little more like:


set use_port to "/dev/cu.usbmodemfa131"

if (get serialport list) contains use_port then

set onMode to true

set myPort to serialport openuse_portbps rate 9600 data bits 8 parity 0 stop bits 1 handshake 0

if myPort ≠ -1 then -- check the port opened correctly

repeat while onMode is true


tell application "Mail"

set x to unread count of inbox


check for new mail

delay 3

set y to unread count of inbox

end tell


if x = y then


serialport write "N" tomyPort

else


serialport write "M" tomyPort

end if



-- add some logic here to determine whether to loop again, e.g.

if foo = bar then set onMode to false

end repeat


serialport closemyPort

end if

end if

Jul 15, 2012 4:21 PM in response to Camelot

Ok thanks this helped me. I just forgot to remove this line from the script when i pasted it in here:


          serialport close use_port

The repeat shouldn't come to an end because he should always print m when a new mail arrives not one time ... everytime a new mail arrives he should print M and as soon as all mails are marked as read he should print N. So i think the repeat loop has to be an infinite loop ?!


Yeah i actually changed this:

tell application "Mail"

set x to unread count of inbox


check for new mail

delay 3

set y to unread count of inbox

end tell


to this:

tell application "Mail"

set x to unread count of inbox

end tell


Thanks for that tip.

Anyway when i run your script or my script i always get the spinning pizza wheel. I just dont know how to manage this.



I just want to implement the behaviour i described before:


"everytime a new mail arrives he should print M in the serial port and as soon as all mails are marked as read he should print N in the serial port"


EDIT: Oh and of course it has to be serialport write "N" to myPort, i forgot to add the port.

Jul 15, 2012 4:37 PM in response to dehlen

OK, that makes a little more sense 🙂


As for an infinite loop - not that you need it here, but I'll get to that - just remove the while clause.

It's perfectly valid to say:


repeat


-- do something

end repeat


and it will run ad infinitum - although you can still use an 'exit repeat' statement within the block to break out.


In this case, though, you don't want a repeat loop at all. What you want is an idle handler.


idle handlers run periodically, on a schedule you define, so on that basis your script would look more like:


set use_port to "/dev/cu.usbmodemfa131"


on idle

if (get serialport list) contains use_port then

set myPort to serialport openuse_portbps rate 9600 data bits 8 parity 0 stop bits 1 handshake 0

if myPort ≠ -1 then -- check the port opened correctly


tell application "Mail"

set x to unread count of inbox

end tell


if x > 0 then

set mailStatus to "M"

else

set mailStatus to "N"

end if


serialport writemailStatustomyPort



serialport closemyPort

end if

end if

return 3 -- check again in 3 seconds

end idle


This differs from your original in that the script kind of 'wakes up', performs its tasks, and then goes to sleep for the duration (defined as the return value at the end of the idle handler). No spinning wheels, wasted CPU cycles, etc.


One variation that you might consider, depending on your application, is to separate the serial port open/close logic from the idle handler. As written, this script periodically (every 3 seconds) opens the port, writes a character, and closes the port again. It might be better for the script to open the port once (at the beginning), and leave the port open until you quit. In that case the script might look more like:


global myPort


on run

set use_port to "/dev/cu.usbmodemfa131"

if (get serialport list) contains use_port then

set myPort to serialport openuse_portbps rate 9600 data bits 8 parity 0 stop bits 1 handshake 0

if myPort = -1 then -- check the port opened correctly

display alert "Ooops, unable to open the serial port " & use_port

tell me to quit

end if

else

display alert "Oops. Serial port not found"

tell me to quit

end if

end run



on idle

tell application "Mail"

set x to unread count of inbox

end tell


if x > 0 then

set mailStatus to "M"

else

set mailStatus to "N"

end if


serialport writemailStatustomyPort


return 3 -- check again in 3 seconds

end idle



on quit

try


serialport closemyPort

end try

continue quit

end quit


In this version, the logic is broken into three distinct parts - the 'run' handler is executed when the script starts, and opens the serial port (or gracefully exits if the port can't be opened).

The comes the idle handler - this is run periodically to check the mail status and write the data to the serial port (this block might warrant some check to ensure the port is open/available, but I'll leave that to you).

Finally comes the quit handler which executes when the script quits. This simply closes the port so that it's not left open.


You'll need to decide whether it's better to periodically open/close the port, or open it once and keep it open for the duration.

Write on Serial port with Applescript

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