(ITP 4-in-4 day 4+1, or how i learned to stop worrying and love blowing deadlines)
to complete the signal to noise meter previously posted i wrote up an apple script which calculates a ratio of messages in my mail inbox to the junk messages which have been caught. the apple script then sends that ratio via serial to the signal to noise meter. i’ve set up a rule in mail.app to trigger the script every time a message comes in. the serial output (ascii only, it seems) is thanks to SerialPort X.
it’s certainly not perfect…having a lot of read messages stagnating in the inbox brings the ratio down…but i’m posting the code below so maybe someone can figure a better way.
also, the script wasn’t triggering when called directly from mail’s rules…my workaround was to have a launcher script run ‘do shell script “osascript ” signalToNoise.scpt’. for some reason this worked when the launcher script was triggered by mail – YMMV.
oh! it just when off as i was writing this entry…the light came on, and the needle swung high….i need to clean out the junk mail!
code after the break (i always wanted to write “after the break”)
Apple Script Code
Make a new script and copy it to your ~/Library/Scripts folder.
tell application "Mail"
set junkCount to unread count of junk mailbox as number
set inboxCount to unread count of inbox as number
(* this returns a count of all the messages in the inbox *)
set inboxMsgs to count messages of inbox
(* this returns only the unread count of the inbox *)
set total to 0
repeat with mb in mailboxes
set total to total + (unread count of mb) as number
end repeat
(* this will count all the messages *)
(*
set mailboxMsgs to 0
repeat with mb in mailboxes
set mailboxMsgs to mailboxMsgs + (count messages of mb)
end repeat
*)
if inboxMsgs > 0 then
set sn to junkCount / (inboxMsgs + junkCount) as number
else
set sn to 0
end if
(* establish the baseline value for the meter *)
if sn < 0.3 then
set sn to 0.3
end if
(*
display dialog ("Signal to Noise - " & sn)
*)
end tell
set portName to (item 1 of (serialport list))
set portRef to serialport open portName bps rate 9600
if portRef is equal to -1 then
display dialog "Could not open Serial Port: " & portName
else
delay 2
set sendVal to 10 * sn as integer
serialport write sendVal to portRef (* sn should be a ratio *)
delay 3
serialport close portRef
end if
(* this will list all the serial ports available *)
(*
serialport list
*)
[/sourcecode]
<h3>Arduino code</h3>
This is for the meter, specifically, but could be easily updated for other output devices.
/*
Signal / noise meter
2009 Robert Carlsen // robertcarlsen.net
driving a mechanical decibel meter with PWM via Arduino
raw analogWrite values:
3 : -4 (bottom of scale)
9 : +6 (top of scale)
draws about 1mA at top of scale
running through an LED and 220ohm resistor to provide more load
and to protect the Arduino from (possible) reverse current as the
springs pull the needle past the electromagnet when it's turned off
*/
int meterPin = 3;
byte val;
int maxVal = 40; // this is adjusted for the load of the meter, resistor and led
int inputMode = 0;
int numModes = 3;
void setup() {
pinMode(meterPin, OUTPUT);
Serial.begin(9600);
}
void loop(){
if(Serial.available()){
val = Serial.read();
Serial.flush();
// change modes
if(val == 255){
inputMode = (inputMode + 1) % numModes;
val = 0;
return;
}
// allow mode switching. default is to accept ascii 0-9
// second mode is to accept raw bytes 0-254
// third mode echos the received values for testing
switch(inputMode){
case 0: // direct input from Serial Monitor
// converting ascii values to int for math
val = constrain(val,48,57) - 48;
// mapping to a useable range
val = map(val,0,9,0,maxVal);
break;
case 1: // input bytes
// reserve 255 for changing mode
val = map(val,0,254,0,maxVal);
break;
case 2: // monitor input values
Serial.print(val , DEC);
break;
}
}
// send value:
if(inputMode != 2)
analogWrite(meterPin, (int)val);
delay(100);
}
Leave a Reply
You must be logged in to post a comment.