I think you wouldn't be pleased if some unimportant call or, what is much worse, SPAM SMS message wakes you up. Solution would be to switch silent profile when you sleep. You can do it by hand ever day, but why not to automate it? You can use
silencer, but it has very simple logic, which silences phone when it is late, but not when you sleep. What about something more intelligent?
This is second article about ET-Prolog. First article was not rated high, i suspect because nobody understood how to work with it. So here is a practical example. You would need
ET-Prolog to run programs, described here. New version of ET-Prolog already includes code, described here.
Simple silencer approach
Ensure, that your et-prolog/init.pl contains
consult('/opt/maemo/usr/lib/et-prolog/n900utils.pl'),
initPhoneProfile,
It is general initialization needed for most cases. Add following code to et-prolog/init.pl:
addGuard(newAlarmTerm('time to sleep', false, '(*.*.* 23:00)-(*.*.* 10:00)'), [[changedGuard]], 'et-prolog/simple_silent_sleep.pl'),
It says, that we need new temporal term called "time to sleep" which becomes true at 23:00 and becomes false at 10:00. When it changes value et-prolog/simple_silent_sleep.pl should be executed. Save init.pl and start editing et-prolog/simple_silent_sleep.pl
(
alarmTerm('true', 'time to sleep'),
(previous(alarmTerm('false', 'time to sleep'));\+(previous(_))),
string_to_atom(PROFILESTR, 'silent'), phoneProfile(PROFILESTR)
);(
alarmTerm('false', 'time to sleep'),
(previous(alarmTerm('true', 'time to sleep'));\+(previous(_))),
string_to_atom(PROFILESTR, 'general'), phoneProfile(PROFILESTR)
);true.
This means: if it is time to sleep now, but was not a moment ago or it is time to sleep and we don't know what was a moment ago, switch to silent profile. if it is not time to sleep now, but was a moment ago or it is not time to sleep and we don't know what was a moment ago, switch to general profile.
That's all. It took only 15 lines of code.
Making things complicated
I don't always go to bed at 23:00 and stand up at 10. But I usually set alarm, when I get up early and I switch light when I go to bed. So I want my phone switch to general profile when alarm rings, or at 10:00 if I haven't set an alarm. And I want it to go to silent mode not at 23:00 but after 23:00 when it becomes dark (remember, that we have ambient light sensor). This program would be much more complicated, about two screens of code, but still much less than it would take on usual programming language.
Ensure, that your et-prolog/init.pl contains
consult('/opt/maemo/usr/lib/et-prolog/n900utils.pl'),
initPhoneProfile,
Add following code to et-prolog/init.pl:
% Switching silent profile at night
newTemporalTerm('notification events', false),
newTemporalTerm('slept', false),
addGuard(newTemporalTerm('wait for dark', 'false'), [[changedGuard]], 'et-prolog/wait_for_dark.pl'),
addGuard(newTemporalTerm('sleeping', 'false'), [[changedGuard]], 'et-prolog/sleep_profile.pl'),
addGuard(newTemporalTerm('alarm ringing', false), [[nEqualGuard(false)]], 'et-prolog/silent_sleep.pl'),
addGuard(newAlarmTerm('time to sleep', false, '(*.*.* 23:00)-(*.*.* 10:00)'), [[changedGuard]], 'et-prolog/silent_sleep.pl'),
addDBusListener('method_call', '/org/freedesktop/Notifications', 'org.freedesktop.Notifications', 'Notify', true, false, temporalTerm(_, 'notification events')),
addGuard(temporalTerm(_, 'notification events'), [[nEqualGuard(false)]], 'et-prolog/notification_eval.pl'),
consult('et-prolog/silent_sleep.pl'),
Here we define several temporal terms and set up actions, that should be taken when these terms change value or are equal/less than specific value. We also register DBus listener which is needed for catching alarms. Let's start with helper scripts.
Catchng alarm
et-prolog/notification_eval.pl should contain
?- write('Notification recieved'),
(
temporalTerm(['notify-clock-alarm' | _], 'notification events'),
addHint('alarm ringing', true),
addHint('alarm ringing', false),
write('Alarm ringing')
); true.
If the first argument of received event is 'notify-clock-alarm', change 'alarm ringing' value to true and then to false. Alarm ringing would be true only during one epoch. This is how events are modeled in ET-Prolog.
Waiting for dark
et-prolog/wait_for_dark.pl should contain
?-
(
temporalTerm('true', 'wait for dark'),
(previous(temporalTerm('false', 'wait for dark'));\+(previous(_))),
addTimerHint(lightSensor(_, 0, 1), 60),
addGuard(lightSensor(_, 0, 1), [[lessGuard(50)]], 'et-prolog/silent_sleep.pl'),
addGuard(lightSensor(_, 0, 1), [[alwaysGuard]], '')
);(
temporalTerm('false', 'wait for dark'),
(previous(temporalTerm('true', 'wait for dark'));\+(previous(_))),
delTimerHint(lightSensor(_, 0, 1), 60),
delGuard(lightSensor(_, 0, 1), [[lessGuard(50)]], 'et-prolog/silent_sleep.pl'),
delGuard(lightSensor(_, 0, 1), [[alwaysGuard]], '')
);true.
You have already seen similar code in simple example. If 'wait for dark' has changed from false to true then start polling light sensor once a minute and call et-prolog/silent_sleep.pl if it is less, than 50. Additional guard with empty script name is needed because ET-Prolog may forget temporal terms values if there are no scripts interested in them.
If 'wait for dark' has changed from true to false, then we don't need to watch for light sensor.
Switching profiles
et-prolog/sleep_profile.pl should contain
?-
(
temporalTerm('true', 'sleeping'),
previous(temporalTerm('false', 'sleeping')),
string_to_atom(PROFILESTR, 'silent'), phoneProfile(PROFILESTR)
);(
temporalTerm('false', 'sleeping'),
previous(temporalTerm('true', 'sleeping')),
string_to_atom(PROFILESTR, 'general'), phoneProfile(PROFILESTR)
);(
% Only possible if there is no previous epoch
true
).
The same scheme. If user sleeps now but didn't sleep before, switch to silent profile. And switch to general profile when user stops sleeping. Notice, that if user changes profile manually when phone thinks, that he is sleeping, profile would remain general. So you can make phone understand, that this night it should wake you up.
Main logic
et-prolog/silent_sleep.pl should contain
?-
((
% Alarm rang, not sleeping any more
temporalTerm('true', 'alarm ringing'),
addHint('sleeping', false),
addHint('wait for dark',false)
); true),
Alarm means, that user is not sleeping. addHint('wait for dark',false) was added in a case if alarm rang when ET-Prolog was only waiting untill it becomes dark. If we won't do it, light sensor would still be polled and it would drain your battery.
(
% Time to sleep, user is not sleeping, and had not slept this night
temporalTerm('false', 'sleeping'),
temporalTerm('false', 'slept'),
alarmTerm('true', 'time to sleep'),
write('Time to sleep'),
If one of these terms has other value this subgoal would not succeed and ET-Prolog would process next alternative.
((
% Last 5 minutes it was dark
always(((ago(SECONDS), SECONDS > 300); (lightSensor(LIGHT, 0, 1), LIGHT < 50))),
sometimes((ago(SECONDS), SECONDS > 300)),
When program starts there is no information about previous epochs, so always(...) would succeed. That's why we ensure, that we have epoch older than 300 seconds.
write('User sleeps'),
addHint('sleeping', true),
addHint('slept', true),
addHint('wait for dark',false)
We just add hints. If it would lead to temporal term values changes, than guards would work and needed scripts would be run automatically. We have 'slept' term which is true, when user has already slept at this day, so we should not expect him to sleep again even if it is still early morning.
);(
% It is light here, check light sensor every minute
write('Waiting until it becomes dark'),
addHint('wait for dark',true)
))
);(
% Sleeping time is over, time to get up
alarmTerm('false', 'time to sleep'),
previous(alarmTerm('true', 'time to sleep')),
write('It is morning'),
addHint('slept', false),
addHint('sleeping', false),
addHint('wait for dark',false)
);
Following true is just to make this goal succeed if we don't need to perform any actions.
Future improvements
When I go to bed it is usually silent around. So phone could use it microphone to check, that I'm sleeping. But I didn't have time to implement ambient noise level term in ET-Prolog.
It is not pleasant to find out, that phone has discharged at night and you don't have a time to charge it. If phone's battery is low and I went to bed I can ask me to charge it, before i fall asleep.
If there was answering machine application for n900 it would be possible to warn caller that user is sleeping, give him a time to decline call and if he didn't threat call as urgent and ring.
Comments
Problem with activation
Hi there, I dont know if I am writing in a proper board but I have got a problem with activation, link i receive in email is not working... [URL WAS HERE]
Try using "I've forgot my
Try using "I've forgot my password" feature (right under login form). If it doesn't work, tell me your nickname, so I would be able to activate it by hand.
I'll look at activation procedure too.
Check accelerators
Why not check for DARK, TIME and NO-MOTION.
When you are out, and carry your phone in your pocket, its probably dark, and it might be past 11pm so your phone will turn silent. BUT if you check the accelerators and the phone is moving, it should prevent the phone from switching to silent.
Normally when you go to bead, you'll place your phone somewhere, so:
Check time -> If time >= 23 && time <= 8 then check DARK, if DARK is true, check for NoMotion, if no NoMotion for 30min, turn phone silent.
Cheers
Bjoern
Additional idea (accelerometer)
Just as additional idea:
If your phone is in the pocket, the phone would see its dark. So if you additionally check that there is no moving when its dark by getting the accelerometers this case would be handled.
Gunni
Accelerometer support
just having a quick read of
just having a quick read of this from my n900! fantastic ideas here! i could have done with something like this, this morning when my i got a load of server down messages at 8am.
thanks a lot, ill be trying this out tonight.
andy (teh @ maemo)
Smart!
I agree, your very much putting the 'smart' into smart phone. This is something I've thought about but had no idea how to implement. For example I'd like to have a mode where the phone switches to 'vibrate' every time I put it in my pocket. Given something like this I could have it check for darkness, and maybe ambient noise. And the sleep idea is great too. When its dark, and there's no noise assume sleep. Very cool indeed.
You have proximity sensor on
Why the painful license agreement?
Asking for an email address before download, a form filling and adding restrictions to the license? If you are lacking feedback on ETProlog as seems to be the case, don't be surprised. I was interested until I saw these restrictions.
You really think, that this
smart phone
If there was answering machine application for n900 it would be possible to warn caller that user is sleeping, give him a time to decline call and if he didn't threat call as urgent and ring.
Now that's what I'd call a smart phone. I'd also like to see location awareness for switching profiles. At $gym I want silent profile, or at $lunch-place, for instance. ;-)
Way to go!
Location awareness and profile switching
Location support is already implemented through liblocation integration. Profile switching is also supported. So your use case can already be expressed in ET-Prolog.
In example init.pl (coming with with ET-Prolog) there is "switching silent profiles during lections in university". It has not been tested thoroughly yet but should work. You can adopt this example for your needs.
You should also select correct location method. GNSS method which uses GPS receiver drains battery so you should stick to ACWP method which is cellular base station based. It is much less precise but doesn't lead to battery drain and works inside buildings.