omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    How to Support Multipeer Connectivity ?

    Pythonista
    9
    57
    36093
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • wolf71
      wolf71 last edited by

      Pythonista can support iOS Multipeer Connectivity?
      who can show some sample code?

      Webmaster4o 1 Reply Last reply Reply Quote 0
      • Webmaster4o
        Webmaster4o @wolf71 last edited by

        @wolf71 You'll have to elaborate a bit more on exactly what you want for those of us who aren't familiar

        1 Reply Last reply Reply Quote 0
        • ccc
          ccc last edited by ccc

          https://developer.apple.com/reference/multipeerconnectivity

          1 Reply Last reply Reply Quote 2
          • wolf71
            wolf71 last edited by

            MCSession=ObjCClass('MCSession')

            Error:
            no objective-C class named 'MCSession' found

            1 Reply Last reply Reply Quote 0
            • lukaskollmer
              lukaskollmer last edited by

              @wolf71 You first need to load the MultipeerConnectivity Framework:

              NSBundle.bundle(Path="/System/Library/Frameworks/MultipeerConnectivity.framework").load()
              
              1 Reply Last reply Reply Quote 0
              • wolf71
                wolf71 last edited by

                Thanks @lukaskollmer, It's work.

                1 Reply Last reply Reply Quote 0
                • wolf71
                  wolf71 last edited by wolf71

                  how to set the MCNearByServiceBrowser Delegate,so can using pythonista handle callback ? I Try this,but not work.
                  !!crash!!

                  Multipeer Connectivity Ref: https://developer.apple.com/library/ios/documentation/MultipeerConnectivity/Reference/MultipeerConnectivityFramework/index.html#//apple_ref/doc/uid/TP40013328

                  from objc_util import *
                  import ctypes,time,os
                  
                  NSBundle.bundle(Path="/System/Library/Frameworks/MultipeerConnectivity.framework").load()
                  MCPeerID=ObjCClass('MCPeerID')
                  MCSession=ObjCClass('MCSession')
                  MCNearbyServiceAdvertiser=ObjCClass('MCNearbyServiceAdvertiser')
                  MCNearbyServiceBrowser=ObjCClass('MCNearbyServiceBrowser')
                  
                  def browser_foundPeer_withDiscoverInfo_(_self, _cmd, _browser, _peerID, _info):
                  	print '!!!!!!!!!!'
                  	#print 'Service found:', ObjCInstance(_info)
                  
                  BrowserDelegate = create_objc_class('BrowserDelegate',methods=[browser_foundPeer_withDiscoverInfo_],protocols=['MCNearbyServiceBrowserDelegate'])
                  
                  myID = MCPeerID.alloc().initWithDisplayName('Wolf_Audio')
                  #mySession = MCSession.alloc().initWithPeer_(myID)
                  
                  #aSrv = MCNearbyServiceAdvertiser.alloc().initWithPeer_discoveryInfo_serviceType_(myID,None,'AudioSrv')
                  # set delegate
                  #aSrv.setDelegate_(MCDelegate.alloc().init())
                  #aSrv.startAdvertisingPeer()
                  
                  aBr = MCNearbyServiceBrowser.alloc().initWithPeer_serviceType_(myID,'AudioSrv')
                  #aBr.setDelegate_(BrowserDelegate.alloc().init())
                  aBr.startBrowsingForPeers()
                  
                  time.sleep(10)
                  
                  aBr.stopBrowsingForPeers()
                  #aSrv.stopAdvertisingPeer()
                  
                  
                  1 Reply Last reply Reply Quote 0
                  • lukaskollmer
                    lukaskollmer last edited by

                    Are you using Python 2 or Python 3?

                    1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB last edited by

                      It is probably a bad idea to pass in alloc().init() into an objc method in the argument directly. objc_util does not retain arguments by default, so what happens is the ObjCInstance is created, a pointer to the class is sent to the objc side of the world, then the object is promptly destroyed in python as it falls out of scope. It sort of depends whether the reference counter gets incremented on the objc side, but basically it is a good idea to separately create a variable and pass it in.

                      So, just use mydelegate=BrowserDelegate.alloc().init(), and pass that into your other methods.

                      aBr.setDelegate_(mydelegate)

                      I could not get your code to crash after fixing this, but I also don't think I have a peer around to trigger the callback. There could be other issuex. If you have pythonista 3, you should install dgelessus's pythonista_startup's enable_fault_handler to tell you where the crash is occuring.

                      If you get this working, please do report back as others may find this useful.

                      wolf71 1 Reply Last reply Reply Quote 0
                      • dgelessus
                        dgelessus last edited by

                        @JonB I'm no Objective-C expert, but shouldn't the result of XYSomeClass.alloc().init() start out retained? I thought the Objective-C convention was that objects returned from alloc..., copy..., mutableCopy... or new... methods don't need to be retained by hand.

                        Also objc_util.ObjCInstance automatically retains and releases the underlying object in the Python __new__ and __del__ methods, so as long as the ObjCInstance is alive in Python, the Objective-C instance is too. And Python functions keep their arguments alive for the duration of the function call (except in some VERY specially written function code), so an ObjCInstance should never be garbage-collected during a method call.

                        By the way, if you only want to install the faulthandler and Objective-C exception handler, you can copy the code for that from this Gist. The rest of my pythonista_startup code can be found in the main repo.

                        1 Reply Last reply Reply Quote 0
                        • wolf71
                          wolf71 @JonB last edited by wolf71

                          @JonB Thanks
                          using your method chage the program. but crash again.
                          I think it maybe this class delegate var problem.

                          =============================
                          delegate
                          Property
                          The delegate object that handles browser-related events.

                          Declaration
                          SWIFT
                          weak var delegate: MCNearbyServiceBrowserDelegate?
                          OBJECTIVE-C
                          @property(weak, nonatomic) id< MCNearbyServiceBrowserDelegate > delegate

                          Fatal Python error: Aborted

                          Thread 0x000000016e247000 (most recent call first):


                          Objective-C exception details:

                          NSInvalidArgumentException: Invalid serviceType passed to MCNearbyServiceBrowser

                          Stack trace:

                          0 CoreFoundation 0x0000000181f02dc8 <redacted> + 148
                          1 libobjc.A.dylib 0x0000000181567f80 objc_exception_throw + 56
                          2 CoreFoundation 0x0000000181f02cf8 <redacted> + 0
                          3 MultipeerConnectivity 0x000000019466a6fc <redacted> + 424
                          4 PythonistaKit 0x0000000101aa7044 ffi_call_SYSV + 68
                          5 PythonistaKit 0x0000000101aaca78 ffi_call_int + 1160
                          6 PythonistaKit 0x0000000101aac5e4 ffi_call + 56
                          7 PythonistaKit 0x00000001018af4a0 _ctypes_callproc + 820
                          8 PythonistaKit 0x00000001018b4374 PyCFuncPtr_call + 1048
                          9 PythonistaKit 0x0000000101419c04 PyObject_Call + 124
                          10 PythonistaKit 0x0000000101650304 PyEval_EvalFrameEx + 2032
                          11 PythonistaKit 0x000000010164f8c4 PyEval_EvalCodeEx + 1604
                          12 PythonistaKit 0x00000001013eb9f0 function_call + 152
                          13 PythonistaKit 0x0000000101419c04 PyObject_Call + 124
                          14 PythonistaKit 0x00000001014082c8 instancemethod_call + 180
                          15 PythonistaKit 0x0000000101419c04 PyObject_Call + 124
                          16 PythonistaKit 0x00000001013945f0 slot_tp_call + 68
                          17 PythonistaKit 0x0000000101419c04 PyObject_Call + 124
                          18 PythonistaKit 0x00000001016507b4 PyEval_EvalFrameEx + 3232
                          19 PythonistaKit 0x000000010164f8c4 PyEval_EvalCodeEx + 1604
                          20 PythonistaKit 0x000000010164f274 PyEval_EvalCode + 44
                          21 PythonistaKit 0x00000001016e02e8 run_mod + 60
                          22 PythonistaKit 0x00000001016e03bc PyRun_FileExFlags + 148
                          23 PythonistaKit 0x00000001016dfe34 PyRun_SimpleFileExFlags + 696
                          24 PythonistaKit 0x00000001016270c4 -[PythonInterpreter runWithOptions:] + 2008
                          25 PythonistaKit 0x00000001016275c4 -[PythonInterpreter doDispatchBlockOnInterpreterThread:] + 108
                          26 Foundation 0x00000001828d802c <redacted> + 340
                          27 CoreFoundation 0x0000000181eb909c <redacted> + 24
                          28 CoreFoundation 0x0000000181eb8b30 <redacted> + 540
                          29 CoreFoundation 0x0000000181eb6830 <redacted> + 724
                          30 CoreFoundation 0x0000000181de0c50 CFRunLoopRunSpecific + 384
                          31 Foundation 0x00000001827f0cfc <redacted> + 308
                          32 Foundation 0x0000000182811ad8 <redacted> + 96
                          33 Foundation 0x00000001828d7e4c <redacted> + 1000
                          34 libsystem_pthread.dylib 0x0000000181b67b28 <redacted> + 156
                          35 libsystem_pthread.dylib 0x0000000181b67a8c <redacted> + 0
                          36 libsystem_pthread.dylib 0x0000000181b65028 thread_start + 4

                          End of exception details.

                          1 Reply Last reply Reply Quote 0
                          • dgelessus
                            dgelessus last edited by

                            @wolf71

                            NSInvalidArgumentException: Invalid serviceType passed to MCNearbyServiceBrowser
                            

                            Your service type "AudioSrv" is not valid - the documentation for -[MCNearbyServiceBrowser initWithPeer:serviceType:] says the following about serviceType:

                            • Must be 1-15 characters long
                            • Can contain only ASCII lowercase letters, numbers and hyphens.

                            This means that "audiosrv" or "audio-srv" would be valid service types, but "AudioSrv" is not, because it contains an uppercase A and S.

                            wolf71 1 Reply Last reply Reply Quote 0
                            • wolf71
                              wolf71 @dgelessus last edited by wolf71

                              @dgelessus I change it to 'audio-srv' ,it's also crash.

                              Objective-C exception details:

                              NSInvalidArgumentException: -[BrowserDelegate_2 browser:foundPeer:withDiscoveryInfo:]: unrecognized selector sent to instance 0x1499625a0

                              Stack trace:

                              0 CoreFoundation 0x0000000181f02dc8 <redacted> + 148
                              1 libobjc.A.dylib 0x0000000181567f80 objc_exception_throw + 56
                              2 CoreFoundation 0x0000000181f09c4c <redacted> + 0
                              3 CoreFoundation 0x0000000181f06bec <redacted> + 872
                              4 CoreFoundation 0x0000000181e04c5c _CF_forwarding_prep_0 + 92
                              5 libdispatch.dylib 0x000000018194d4bc <redacted> + 24
                              6 libdispatch.dylib 0x000000018194d47c <redacted> + 16
                              7 libdispatch.dylib 0x0000000181952b84 _dispatch_main_queue_callback_4CF + 1844
                              8 CoreFoundation 0x0000000181eb8d50 <redacted> + 12
                              9 CoreFoundation 0x0000000181eb6bb8 <redacted> + 1628
                              10 CoreFoundation 0x0000000181de0c50 CFRunLoopRunSpecific + 384
                              11 GraphicsServices 0x00000001836c8088 GSEventRunModal + 180
                              12 UIKit 0x00000001870c6088 UIApplicationMain + 204
                              13 Pythonista3 0x00000001000a81c8 Pythonista3 + 180680
                              14 libdyld.dylib 0x000000018197e8b8 <redacted> + 4

                              End of exception details.

                              1 Reply Last reply Reply Quote 0
                              • dgelessus
                                dgelessus last edited by

                                OK, it's a different error, we are making progress :)

                                Now it's saying that it can't find the method browser:foundPeer:withDiscoveryInfo: on your delegate. It looks like you mistyped the name in your code (you wrote withDiscoverInfo, it should be withDiscoveryInfo, note the y in Discovery).

                                wolf71 1 Reply Last reply Reply Quote 0
                                • wolf71
                                  wolf71 @dgelessus last edited by wolf71

                                  @dgelessus Thank you very much.

                                  edit the bug, but can you tell me how to process the browser:lostPeer: delegate?

                                  Ref: https://developer.apple.com/library/ios/documentation/MultipeerConnectivity/Reference/MCNearbyServiceBrowserDelegateRef/index.html#//apple_ref/occ/intfm/MCNearbyServiceBrowserDelegate/browser:lostPeer:

                                  ======================================
                                  Fatal Python error: Aborted

                                  Thread 0x000000016e2d3000 (most recent call first):


                                  Objective-C exception details:

                                  NSInvalidArgumentException: -[BrowserDelegate_6 browser:lostPeer:]: unrecognized selector sent to instance 0x134eb9c40

                                  Stack trace:

                                  0 CoreFoundation 0x0000000181f02dc8 <redacted> + 148
                                  1 libobjc.A.dylib 0x0000000181567f80 objc_exception_throw + 56
                                  2 CoreFoundation 0x0000000181f09c4c <redacted> + 0
                                  3 CoreFoundation 0x0000000181f06bec <redacted> + 872
                                  4 CoreFoundation 0x0000000181e04c5c _CF_forwarding_prep_0 + 92
                                  5 libdispatch.dylib 0x000000018194d4bc <redacted> + 24
                                  6 libdispatch.dylib 0x000000018194d47c <redacted> + 16
                                  7 libdispatch.dylib 0x0000000181952b84 _dispatch_main_queue_callback_4CF + 1844
                                  8 CoreFoundation 0x0000000181eb8d50 <redacted> + 12
                                  9 CoreFoundation 0x0000000181eb6bb8 <redacted> + 1628
                                  10 CoreFoundation 0x0000000181de0c50 CFRunLoopRunSpecific + 384
                                  11 GraphicsServices 0x00000001836c8088 GSEventRunModal + 180
                                  12 UIKit 0x00000001870c6088 UIApplicationMain + 204
                                  13 Pythonista3 0x00000001000b01c8 Pythonista3 + 180680
                                  14 libdyld.dylib 0x000000018197e8b8 <redacted> + 4

                                  End of exception details.

                                  1 Reply Last reply Reply Quote 0
                                  • JonB
                                    JonB last edited by

                                    That bug is saying that it tried to call broswe:lostPeer:, but your object did not implement it.
                                    The protocol reference shows those as required.

                                    Simply create a method

                                    def browser_lostPeer_(_self, _cmd, browser, peer):
                                       print ('lost peer')
                                    

                                    and when you create the class pass both methods in the methods argument

                                    ... methods=[browser_lostPeer_, browser_foundPeer_withDiscoveryInfo_], ...
                                    
                                    wolf71 2 Replies Last reply Reply Quote 0
                                    • wolf71
                                      wolf71 @JonB last edited by

                                      @JonB Thank you very much.
                                      It's work !!!

                                      1 Reply Last reply Reply Quote 0
                                      • wolf71
                                        wolf71 @JonB last edited by

                                        @JonB can you tell me how write this type delegate.

                                        invitationHandler:(void (^)(BOOL accept,
                                        MCSession *session))invitationHandler

                                        def advertiser_didReceiveInvitationFromPeer_withContext_invitationHandler_(_self,_cmd,_advertiser,_peerID,_context,_invitationHandler):
                                        	print 'ppppppp'
                                        
                                        

                                        OBJECTIVE-C

                                        • (void)advertiser:(MCNearbyServiceAdvertiser *)advertiser
                                          didReceiveInvitationFromPeer:(MCPeerID *)peerID
                                          withContext:(NSData *)context
                                          invitationHandler:(void (^)(BOOL accept,
                                          MCSession *session))invitationHandler
                                        1 Reply Last reply Reply Quote 0
                                        • JonB
                                          JonB last edited by

                                          What you have looks right. Add it to the methods argument of your delegate, and also add the right protocol to your delegate class. MCNearbyServiceAdvertiserDelegate

                                          You are requires to call the handler block with a boolean accept argument, and a MCSession initalized from the peer. StackOverflow gives me:

                                          accept=true
                                          session = ObjCClass('MCSession').alloc().initWithPeer(peerID)
                                          session.delegate = YOURSERVICEADVERTISERDELEGATE
                                          ObjCInstance(handler).invoke(accept, session)
                                          

                                          Disclaimer... I don't have anything to test out, you need o find a good end to end example written in ObjC or swift to port over... some of these frameworks are tricky to work with just from the docs alone.

                                          wolf71 1 Reply Last reply Reply Quote 0
                                          • wolf71
                                            wolf71 @JonB last edited by wolf71

                                            @JonB you can using this test code.
                                            Server side:

                                            # -*- coding: utf-8 -*-
                                            
                                            from objc_util import *
                                            import ctypes,time,os
                                            
                                            NSBundle.bundle(Path="/System/Library/Frameworks/MultipeerConnectivity.framework").load()
                                            MCPeerID=ObjCClass('MCPeerID')
                                            MCSession=ObjCClass('MCSession')
                                            MCNearbyServiceAdvertiser=ObjCClass('MCNearbyServiceAdvertiser')
                                            MCNearbyServiceBrowser=ObjCClass('MCNearbyServiceBrowser')
                                            
                                            # Session Delegate 
                                            def session_peer_didChangeState_(_self,_cmd,_session,_peerID,_state):
                                            	print 'session change',_peerID,_session,_state
                                            
                                            def session_didReceiveData_fromPeer_(_self,_cmd,_session,_data,_peerID):
                                            	print 'Received Data',_data
                                            
                                            def session_didReceiveStream_withName_fromPeer_(_self,_cmd,_session,_stream,_streamName,_peerID):
                                            	print 'Received Stream....',_streamName 
                                            	
                                            SessionDelegate = create_objc_class('SessionDelegate',methods=[session_peer_didChangeState_, session_didReceiveData_fromPeer_, session_didReceiveStream_withName_fromPeer_],protocols=['MCSessionDelegate'])
                                            SDelegate = SessionDelegate.alloc().init()
                                            
                                            # Advertiser Delegate 
                                            def advertiser_didReceiveInvitationFromPeer_withContext_invitationHandler_(_self,_cmd,advertiser,peerID,context,invitationHandler):
                                            	print 'ppppppp'
                                            	#ObjCInstance(invitationHandler).invoke(True,mySession)
                                            	
                                            AdvertiserDelegate = create_objc_class('AdvertiserDelegate',methods=[advertiser_didReceiveInvitationFromPeer_withContext_invitationHandler_],protocols=['MCNearbyServiceAdvertiserDelegate'])
                                            ADelegate = AdvertiserDelegate.alloc().init()		
                                            
                                            
                                            # init PeerID
                                            myID = MCPeerID.alloc().initWithDisplayName('wolf_srv')
                                            # init Session and delegate
                                            mySession = MCSession.alloc().initWithPeer_(myID)
                                            mySession.setDelegate_(SDelegate)
                                            
                                            
                                            '''
                                            	Server 
                                            '''
                                            # Create Server and set delegate
                                            aSrv = MCNearbyServiceAdvertiser.alloc().initWithPeer_discoveryInfo_serviceType_(myID,ns({'player.name':'apple'}),'audio-srv1')
                                            aSrv.setDelegate_(ADelegate)
                                            
                                            # Start Server
                                            aSrv.startAdvertisingPeer()
                                            print 'Server start, ID is : ',myID
                                            
                                            try:
                                            	while 1:
                                            		time.sleep(0.1)
                                            except KeyboardInterrupt:
                                            	print 'Server Stop...'
                                            	aSrv.stopAdvertisingPeer()
                                            except:            
                                            	raise
                                            

                                            =================================
                                            Browser side

                                            # -*- coding: utf-8 -*-
                                            
                                            from objc_util import *
                                            import ctypes,time,os
                                            
                                            cnt = 0
                                            
                                            NSBundle.bundle(Path="/System/Library/Frameworks/MultipeerConnectivity.framework").load()
                                            MCPeerID=ObjCClass('MCPeerID')
                                            MCSession=ObjCClass('MCSession')
                                            MCNearbyServiceAdvertiser=ObjCClass('MCNearbyServiceAdvertiser')
                                            MCNearbyServiceBrowser=ObjCClass('MCNearbyServiceBrowser')
                                            
                                            def session_peer_didChangeState_(_self,_cmd,_session,_peerID,_state):
                                            	print 'session change',ObjCInstance(_peerID),_state
                                            
                                            def session_didReceiveData_fromPeer_(_self,_cmd,_session,_data,_peerID):
                                            	print 'Received Data',_data
                                            
                                            def session_didReceiveStream_withName_fromPeer_(_self,_cmd,_session,_stream,_streamName,_peerID):
                                            	print 'Received Stream....',_streamName 
                                            	
                                            SessionDelegate = create_objc_class('SessionDelegate',methods=[session_peer_didChangeState_, session_didReceiveData_fromPeer_, session_didReceiveStream_withName_fromPeer_],protocols=['MCSessionDelegate'])
                                            SDelegate = SessionDelegate.alloc().init()
                                            
                                            def browser_didNotStartBrowsingForPeers_(_self,_cmd,_browser,_err):
                                            	print ('ERROR!!!')
                                            
                                            def browser_foundPeer_withDiscoveryInfo_(_self, _cmd, _browser, _peerID, _info):
                                            	global aBr,mySession
                                            	
                                            	peerID = ObjCInstance(_peerID)
                                            	aBr.invitePeer_toSession_withContext_timeout_(peerID,mySession,None,0)
                                            	#mySession.connectPeer_withNearbyConnectionData_(peerID,None)
                                            	print '#',peerID,ObjCInstance(_info)
                                            	
                                            def browser_lostPeer_(_self, _cmd, browser, peer):
                                            	print ('lost peer')
                                            
                                            BrowserDelegate = create_objc_class('BrowserDelegate',methods=[browser_foundPeer_withDiscoveryInfo_, browser_lostPeer_, browser_didNotStartBrowsingForPeers_],protocols=['MCNearbyServiceBrowserDelegate'])
                                            Bdelegate = BrowserDelegate.alloc().init()
                                            
                                            myID = MCPeerID.alloc().initWithDisplayName('wolf_client')
                                            mySession = MCSession.alloc().initWithPeer_(myID)
                                            mySession.setDelegate_(SDelegate)
                                            
                                            print 'my ID',myID
                                            aBr = MCNearbyServiceBrowser.alloc().initWithPeer_serviceType_(myID,'audio-srv1')
                                            aBr.setDelegate_(Bdelegate)
                                            aBr.startBrowsingForPeers()
                                            
                                            try:
                                            	while 1:
                                            		time.sleep(0.1)
                                            except KeyboardInterrupt:
                                            	print 'Close...'
                                            	aBr.stopBrowsingForPeers()	
                                            except:            
                                            	raise
                                            
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors