Try to get info out of GSM
authorEnrico Zini <enrico@enricozini.org>
Fri, 26 Mar 2010 15:34:37 +0000 (15:34 +0000)
committerEnrico Zini <enrico@enricozini.org>
Fri, 26 Mar 2010 15:34:37 +0000 (15:34 +0000)
README
test/test-gsm-receive.vala

diff --git a/README b/README
index 0d17b4ca8aa52d078adcf9c6e41062bdbcb613d7..12d07880c2f1b8e7fd4465ba366f10a58bd1ef5d 100644 (file)
--- a/README
+++ b/README
@@ -176,6 +176,19 @@ TODO list / wish list
  * FSO API "documentation":
  http://git.freesmartphone.org/?p=specs.git;a=blob_plain;f=html/index.html;hb=HEAD
 
+using vala-dbus-binding-tool:
+
+  mdbus -s org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freedesktop.DBus.Introspectable.Introspect > /tmp/api.xml
+  vi /tmp/api.xml
+  convert to xml: 
+    remove quotes at begin and end
+    :$s/\n/^M/g
+  mkdir /tmp/foo
+  vala-dbus-binding-tool --directory=/tmp/foo --api-path=/tmp/api.xml
+
+
+
+
  * Features to add:
  - if GPS time is more than 1 minute and less than 1 hour different than the
    system time, automatically sync it
@@ -194,6 +207,7 @@ TODO list / wish list
     + GSM status on main screen (with messages while coming online, and
       operator, power and so on)
     - log incoming messages
+      (first as a standalone app quick to compile)
     - log and refuse incoming calls
    to "move" the GSM device to my laptop:
     socat FILE:/dev/ttySAC0 TCP-LISTEN:12345,bind=192.168.0.202
index 7ad3542d3c20c3e9dec439c2247f4b6df6ffbabc..b1110f86d075efe88d5aebb52955de6db0f710c4 100644 (file)
@@ -22,6 +22,363 @@ using GLib;
 
 //string VERSION = "0.1";
 
+public class GSMReceive: Object, zavai.Resource
+{
+    public dynamic DBus.Object network;
+    public dynamic DBus.Object call;
+
+    public GSMReceive()
+    {
+        zavai.gsm.gsm.request("GSMReceive");
+
+        network = zavai.registry.sbus.get_object(
+            "org.freesmartphone.ogsmd", 
+            "/org/freesmartphone/GSM/Device",
+            "org.freesmartphone.GSM.Network");
+
+        call = zavai.registry.sbus.get_object(
+                "org.freesmartphone.ogsmd",
+                "/org/freesmartphone/GSM/Device",
+                "org.freesmartphone.GSM.Call");
+
+        network.Status += on_network_Status;
+        network.SignalStrength += on_network_SignalStrength;
+        call.CallStatus += on_call_Status;
+    }
+
+    public void shutdown()
+    {
+        zavai.gsm.gsm.release("GSMReceive");
+    }
+
+    public void on_network_SignalStrength(int strength)
+    {
+        stderr.printf("SIGNAL STRENGTH %d\n", strength);
+    }
+
+    public void on_network_Status(GLib.HashTable<string, GLib.Value?> status)
+    {
+        stderr.printf("NETWORK STATUS\n");
+
+        // dbg("cbNetworkStatus %s" % formatDict(status))
+    }
+
+    public void on_call_Status(int index, string status, GLib.HashTable<string, GLib.Value?> properties)
+    {
+        stderr.printf("CALL STATUS %d %s\n", index, status);
+        /*
+        dbg("cbCallStatus %d, %s, %s" % (id, status, formatDict(properties)))
+        self.status = status
+        if status == "incoming":
+            if "peer" in properties and properties["peer"] == "+358942832031":
+                self.gsm_call_iface.ReleaseAll()
+                os.system("kapula-debug-call-handler &")
+            else:
+                os.system("alsactl restore -f /etc/alsa-scenarios/stereoout-maxvolume.state")
+                os.system("vibrator-start")
+                os.system("ringtone-start")
+                os.system("ledctrl --on-time 400 --off-time 200 gta02-aux:red");
+        if status == "release":
+            os.system("ringtone-stop")
+            os.system("vibrator-stop")
+            os.system("ledctrl --off gta02-aux:red");
+        */
+    }
+
+
+/*
+        def onIncomingUssd( self, mode, message ):
+                logger.info( "USSD Message: %s" % message )
+                        self.main.groups["alert"].activate( "<title>Operator Message</title>%s" % message, [("OK")] )
+    def onCallStatus( self, id, status, properties ):
+        self.call = id
+        self.update_status(status)
+        if not status in ["release"]:
+            if "peer" in properties:
+                self.part_text_set( "label", self.main.groups["contacts"].tryNumberToName( properties[ "peer" ] ) )
+                self.part_text_set( "sublabel", properties[ "peer" ] )
+            else:
+                self.part_text_set( "label", _("unknown number") )
+                self.part_text_set( "sublabel", "" )
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "button_*" )
+    def on_edje_signal_dialer_button_pressed(self, emission, source):
+        key = source.split("_", 1)[1]
+        if key in ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"):
+            dbus_object.gsm_call_iface.SendDtmf( key )
+            self.text.append(key)
+        elif key in "star":
+            dbus_object.gsm_call_iface.SendDtmf( "*" )
+            self.text.append("*")
+        elif key in "hash":
+            dbus_object.gsm_call_iface.SendDtmf( "#" )
+            self.text += "#"
+        # The trailing whitespace is a workaround for the one char invisible
+        # bug due to some problems with scaling of text parts.
+        self.part_text_set("label", "".join(self.text)+" ")
+
+    @edje.decorators.signal_callback("call_button_pressed", "button_right")
+    def on_edje_signal_call_button_right_pressed(self, emission, source):
+        self.main.transition_to("call")
+
+    def sendMessage( self, index ):
+        logger.info( "trying to send message w/ index %d..." % index )
+        dbus_object.gsm_sim_iface.SendStoredMessage( index, reply_handler=self.cbSendReply, error_handler=self.cbSendError )
+
+    def cbSendReply( self, reference, timestamp ):
+        logger.info( "sent message successfully w/ reference number %d (timestamp: %s)" % ( reference, timestamp ) )
+
+    def cbSendError( self, e ):
+        logger.error( "could not send message. leaving in outgoing. error was: %s" % e )
+
+    def cbStoreReply( self, result ):
+        logger.info( "stored message lives at SIM position %d" % result )
+        self.sendMessage( result )
+        if not self.busy:
+            dbus_object.gsm_sim_iface.RetrieveMessagebook(
+                "all",
+                reply_handler=self.cbMessagebookReply,
+                error_handler=self.cbMessagebookError
+            )
+            self.busy = True
+
+    def cbStoreError( self, e ):
+        logger.warning( "error while storing message - %s" % e.get_dbus_name() )
+        if e.get_dbus_name() == "org.freesmartphone.GSM.SIM.MemoryFull":
+            self.main.groups["alert"].activate( "<title>Failed to send message</title>SIM Memory Full", [("OK")] )
+
+    def cbSend1( self, selected, cb_data ):
+        self.main.groups["text_edit"].setup(
+            "sms",
+            "", # text
+            selected[0], # title
+            selected[1], # reference
+            self.cbSend2
+        )
+
+    def cbSend2( self, text, number ):
+        if dbus_object.gsm_device_obj:
+            dbus_object.gsm_sim_iface.StoreMessage(
+                number, text, {},
+                reply_handler=self.cbStoreReply,
+                error_handler=self.cbStoreError
+            )
+
+    def cbDelete( self, result, reference ):
+        if result == "abort":
+            return
+        if dbus_object.gsm_device_obj:
+            dbus_object.gsm_sim_iface.DeleteMessage(
+                reference
+            )
+        for i in range( len( self.messagebook ) ):
+            if self.messagebook[i][0] == reference:
+                del self.messagebook[i]
+                break
+        self.updateList()
+
+    def cbForward( self, selected, text ):
+        if dbus_object.gsm_device_obj:
+            dbus_object.gsm_sim_iface.StoreMessage(
+                selected[1], text, {},
+                reply_handler=self.cbStoreReply,
+                error_handler=self.cbStoreError
+            )
+
+    def cbReply( self, text, number):
+        if dbus_object.gsm_device_obj:
+            dbus_object.gsm_sim_iface.StoreMessage(
+                number, text, {},
+                reply_handler=self.cbStoreReply,
+                error_handler=self.cbStoreError
+            )
+
+    def cbMenu( self, result ):
+        if result == _("send"):
+            self.main.groups["contacts"].prepare()
+            if self.main.groups["contacts"].ready:
+                self.main.groups["list_choose"].setup(
+                    "sms",
+                    [ (x[1], x[2]) for x in  self.main.groups["contacts"].phonebook],
+                    None,
+                    self.cbSend1
+                )
+        elif result == _("delete"):
+            self.main.groups["alert"].activate(
+                _("delete?"),
+                (_("abort"), _("delete")),
+                self.current[self.selected][0], # reference
+                self.cbDelete
+            )
+        elif result == _("forward"):
+            self.main.groups["contacts"].prepare()
+            if self.main.groups["contacts"].ready:
+                self.main.groups["list_choose"].setup(
+                    "sms",
+                    [ (x[1], x[2] ) for x in  self.main.groups["contacts"].phonebook],
+                    self.current[self.selected][3],
+                    self.cbForward
+                )
+        elif result == _("reply"):
+            self.main.groups["text_edit"].setup(
+                "sms",
+                "", # text
+                self.current[self.selected][2], # title = number
+                self.current[self.selected][2], # reference = number
+                self.cbReply
+            )
+
+    def cbMessagebookReply( self, result ):
+        logger.info( "retrieved messagebook: %s" % result )
+        self.busy = False
+        self.messagebook = result
+        self.ready = True
+        self.updateList()
+        self.main.groups["main"].targets["sms"] = True
+        self.main.groups["main"].update()
+        if not self.newindex is None:
+            message = [x for x in self.messagebook if x[0] == self.newindex]
+            self.newindex = None
+            if message and self.main.current_group == self.main.groups["main"]:
+                message = message[0]
+                if "read" in message[1]:
+                    from_to = _("From")
+                    timestamp = message[4]["timestamp"]
+                else:
+                    from_to = _("To")
+                    timestamp = _("Unknown")
+                from_text = self.main.groups["contacts"].tryNumberToName( message[2] )
+                self.main.groups["text_show"].setup(
+                    "sms",
+                    _("%s: %s<br>Date: %s<p>%s") % (
+                        from_to,
+                        from_text,
+                        timestamp,
+                        textblock_escape( message[3] ).replace( '\n', '<br>' )
+                    )
+                )
+            if dbus_object.gsm_device_obj:
+                messagebookInfo = dbus_object.gsm_sim_iface.GetMessagebookInfo()
+                if messagebookInfo["used"] == messagebookInfo["last"]:
+                    self.main.groups["alert"].activate( "<title>Warning</title>SIM Memory Full", [("OK")] )
+
+    def cbMessagebookError( self, e ):
+        logger.warning( "error while retrieving messagebook" )
+        self.busy = False
+
+    def onIncomingMessage( self, index ):
+        logger.info( "new message! Retrieving messagebook..." )
+        self.newindex = index
+        if not self.busy:
+            dbus_object.gsm_sim_iface.RetrieveMessagebook(
+                "all",
+                reply_handler=self.cbMessagebookReply,
+                error_handler=self.cbMessagebookError
+            )
+            self.busy = True
+
+    def prepare( self ):
+        if not self.ready and not self.busy:
+            if dbus_object.gsm_device_obj:
+                logger.info( "retrieving messagebook..." )
+                dbus_object.gsm_sim_iface.RetrieveMessagebook(
+                    "all",
+                    reply_handler=self.cbMessagebookReply,
+                    error_handler=self.cbMessagebookError
+                )
+                self.busy = True
+            else:
+                # Fake messagebook...
+                self.cbMessagebookReply( [
+                    (0, "read", "+4544555", "Hello World!"),
+                    (1, "read", "+456663443", "Zhone!"),
+                    (2, "read", "+456663443", "Hi Guy\nGuess what, I now "+
+                        "know to write multi-line SMSs.\nIsn't that "+
+                        "nice?\n\nSome Buddy"),
+                    (3, "read", "Flash SMS", "An SMS without digits. Strange, isn't it?"),
+                ] )
+
+    def onReadyStatus( self, status ):
+        logger.debug( "SIM is ready: %s" % status )
+        if status:
+            # Force update
+            self.ready = False
+            self.prepare()
+
+    def onShow( self ):
+        self.prepare()
+        self.updateList()
+
+    def updateList( self):
+        self.main.groups["contacts"].prepare()
+        self.pages = max( ( len( self.messagebook ) - 1 ) / 6 + 1, 1 )
+        if self.page >= self.pages:
+            self.page = self.pages - 1
+        if self.page < 0:
+            self.page = 0
+        self.current = self.messagebook[self.page*6:(self.page+1)*6]
+        text = u"".join( [u"□"]*self.page+[u"▣"]+[u"□"]*(self.pages-self.page-1) )
+        self.part_text_set( "pager", text )
+        for i in range( 0, len( self.current ) ):
+            main_text = self.main.groups["contacts"].tryNumberToName( self.current[i][2] )
+            self.part_text_set( "label_main_list_%i" % i, main_text )
+            sub_text = " ".join(self.current[i][3].splitlines())
+            self.part_text_set( "label_sub_list_%i" % i, u"(%s) %s" % ( self.current[i][1], sub_text ) )
+        for i in range( len( self.current ), 6):
+            self.part_text_set( "label_main_list_%i" % i, u"" )
+            self.part_text_set( "label_sub_list_%i" % i, u"" )
+        self.selected = None
+        for i in range( 6 ):
+            self.signal_emit( "deactivate_target_list_%i" % i, "" )
+
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "target_list_*" )
+    def on_edje_signal_button_list_pressed( self, emission, source ):
+        id = int( source.split( "_" )[-1] )
+        if self.selected == id:
+            return
+        if self.selected is not None:
+            self.signal_emit( "deactivate_target_list_%i" % self.selected, "" )
+        self.signal_emit( "activate_target_list_%i" % id, "" )
+        self.selected = id
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_left" )
+    def on_edje_signal_button_action_left_pressed( self, emission, source ):
+        self.page -= 1
+        self.updateList()
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_right" )
+    def on_edje_signal_button_action_right_pressed( self, emission, source ):
+        self.page += 1
+        self.updateList()
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_open" )
+    def on_edje_signal_button_action_open_pressed( self, emission, source ):
+        if self.selected is not None:
+            if "read" in self.current[self.selected][1]:
+                from_to = _("From")
+                timestamp = self.current[self.selected][4]["timestamp"]
+            else:
+                from_to = _("To")
+                timestamp = _("Unknown")
+            from_text = self.main.groups["contacts"].tryNumberToName( self.current[self.selected][2] )
+            self.main.groups["text_show"].setup(
+                "sms",
+                _("%s: %s<br>Date: %s<p>%s") % (
+                    from_to,
+                    from_text,
+                    timestamp,
+                    textblock_escape( self.current[self.selected][3] ).replace( '\n', '<br>' )
+                )
+            )
+
+    @edje.decorators.signal_callback( "mouse,clicked,1", "button_bottom_middle" )
+    def on_edje_signal_button_bottom_middle_pressed( self, emission, source ):
+        self.main.groups["menu"].activate( ( _("send"), _("delete"), _("forward"), _("reply") ), self.cbMenu )
+        self.main.groups["menu"].part_text_set( "target_label_cancel", _("cancel") )
+*/
+}
+
 static int main (string[] args) {
        Gtk.init (ref args);
     Gst.init (ref args);