ET-prolog - making phone smarter

Today many devices we use in everyday life are called "smart". What does it mean? Electronics (at least now) can't be smart, so we speak about intelligence imitation and following rules can be used for measuring its quality:
  • Device should do what user wants
  • If device doesn't obey user, it must tell user why it doesn't obey in such a way, that user would agree, that he was wrong. This is user misstakes control.
  • Device should guess, what user wants, if possible.
That last rule brings the problem. Such a mass production device as mobile phone can't count individuality of each user. This means, that it would guess only most obvious things. There are two ways making device smarter:
  • The best specialists: psychologists, programmers, designers, economists - have already thought for you. This is the best device, it is convenient. Why do you want something else? This is not fashionable. Relax and enjoy. Or, in other words: "Eat what you are given and get used to it".
  • Give ability to customize device. I do not mean themes, appearance, but the behaviour of the device. Usually this leads to tons of checkboxes and buttons in program settings.
    • I hope only second variant is interesting for you. It existed inside single applications for a long time, but now applications have learned to communicate. We have convenient, widely used and unified interprocess communication technologies. They allow applications to announce what they are doing and rule other applications. If you look through n900 repositories you would find many packages, which adjust other applications behaviour to what user wants.
      I would start from classic cron, scheduled command execution:
      • Fcron - classical cron, controlled via configuration file
      • alarm - the same thing, but with less convenient but more simple GUI
      • silencer can only switch phone profiles. But GUI is very simple.
      • sleeper can stop player after specified time.
      But there are many other events that can be reacted, not only timer. Your phone beeps when battery is low, changes display brightness according to ambient light sensor, notebooks regulate powersaving/computation power ratio. You can find packages, that utilize this approach in repositories:
      • headphone daemon pauses music when headphones are unplugged. Good example, when there is no single solution. Maemo developers rejected to add such functionality in firmware because it worked in such a way some time ago, but people complained, that it is not what they want.
      • lockdaemon beeps and vibrates when keyboard is opened. I hate such things, but other love.
      • shake2control allows to control player by shaking phone.
      • geotodo - shows reminders when you are near to specified place.
      But all these programs have the same feature: events on which they react and actions they take are hardcoded. Just imagine how many different events can happen and how many different actions can be taken, multiply these numbers and you would get number of required packages. First what comes in-to mind is to listen for events and let user to determine needed reaction. This is the way chosen by ActionManager and Do What I Mean Daemon developers.
      As far as I know, this is top of technologies used for making phone smarter (not counting self learning techniques). The main limitation is in simplicity of rules. It is hard to perform actions based on several events. Silencer author suggests to activate silent mode at night. But I go to sleep at different time. It would be more correct to enable it from 10 to 2 o'clock when it becomes dark and silent and to disable it in the morning when alarm rang or at 10 o'clock.
      So the idea is to create programming language which would allow quickly and easily, without deep knowledge of interprocess communication, write programs like headphone daemon. And such program should be short, several lines of code, not 272:
      I want to monitor headphone jack
      if player is playing and headphones are not connected now but were connected before, pause music
      Advanced user could easily describe desired phone behaviour with such language. Newbie... would copy scripts from internet or use some GUI scripts generator. Anyway, writing such generator is easier, than writing system state monitoring daemon.
      Described language looks like logic programming language, so SWI-Prolog was selected as base language and an extension, which allows to work with events and temporal logic (we need to operate such conceptions as "at preveous moment", "last 15 minutes", "there was a moment when") was written. In result Event driven Temporal prolog or ET-prolog was born. Headphoned analog could be something like this:
      init.pl
      ?- addGuard(headphonesState(_), [[changedGuard]], 'logic/headphones.pl').
      headphones.pl:
      ?- headphonesState('disconnected\n'),previous(headphonesState('connected\n')),
      (mediaPlayer('started'),pauseMediaPlayer;true),
      (MPlayer('started'),pauseMPlayer;true),
      (Panucci('started'),pausePanucci;true),
      (FMradio('started'),pauseFMRadio;true)
      ;true
      Unfortunately, at this moment player control is not implemented. But once written it can be reused in other scripts. And, if player can be controlled via DBus, it is very easy to implement. For example,. predicate for phone profile switching is implemented like this:
      setPhoneProfile(PROFILE) :- dbusSend('com.nokia.profiled', '/com/nokia/profiled', 'com.nokia.profiled', 'set_profile', [PROFILE]).
      And more complex and complete variant of the same predicate, which looks after profile change and works in true prolog two-way style:
      % Initializes profile term
      ?- 
      	dbusSend(CURRENTPROFILE, 'com.nokia.profiled', '/com/nokia/profiled', 'com.nokia.profiled', 'get_profile', [], false),
      	newTemporalTerm('phone profile', [true,true,CURRENTPROFILE,false]), 
      	addDBusListener('signal', '/com/nokia/profiled', 'com.nokia.profiled', 'profile_changed', false, false, temporalTerm(_, 'phone profile')).
      % silent or general
      phoneProfile(PROFILE) :- string_to_atom(PROFILESTR, PROFILE), temporalTerm([_,_,PROFILESTR | _], 'phone profile');  dbusSend('com.nokia.profiled', '/com/nokia/profiled', 'com.nokia.profiled', 'set_profile', [PROFILESTR], false).
      If this project is interesting for you, you can: ET-Prolog is developed by Dicentra13 - Petrushkina Anastasia (alarmd and liblocation integration, file terms) and KiberGus - Guseynov Alexey (language core, DBus integration)