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.


    Accessing Barometer Measurements

    Pythonista
    barometer sensor
    10
    25
    21501
    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.
    • tszheichoi
      tszheichoi last edited by

      I'm wondering whether it is possible to access the barometer (pressure) measurements on a supported iPhone from within a pythoninsta script? I've tried to use ObjCClass with the corresponding objective C class without much luck.

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

        I wasn't even aware that iPhones had barometer measurements. What code have you tried, maybe someone can help debug?

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

          Models since the iPhone 6 has a built in barometer. I believe it's primarily for measuring how many flights of stairs climbed. But the raw pressure measurements should be accessible:

          https://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CMAltitudeData_class/index.html#//apple_ref/occ/cl/CMAltitudeData

          To be honest, I'm fairly new to Pythoninsta, and am not entirely sure whether objCClass is for this purpose.

          What I'm trying to do is to write a simple utility to map out a pressure and magnetic field variations in underground caves. The latter is possible with the motion module. I'm a caving hobbyist, and want to see whether sensors in phones can aid underground spatial orientation. (GPS obviously doesn't work underground!)

          1 Reply Last reply Reply Quote 1
          • omz
            omz last edited by

            It's a little tricky because of the block-based API, but here's a working example that simply prints altitude/pressure data to the console (until the script is stopped). I've only tested this on an iPad Air 2 (which also has a barometer), but it should work the same on an iPhone 6.

            from objc_util import ObjCInstance, ObjCClass, ObjCBlock, c_void_p
            
            def handler(_cmd, _data, _error):
            	print(ObjCInstance(_data))
            
            handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p, c_void_p, c_void_p])
            
            def main():
            	CMAltimeter = ObjCClass('CMAltimeter')
            	NSOperationQueue = ObjCClass('NSOperationQueue')
            	if not CMAltimeter.isRelativeAltitudeAvailable():
            		print('This device has no barometer.')
            		return
            	altimeter = CMAltimeter.new()
            	main_q = NSOperationQueue.mainQueue()
            	altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler_block)
            	print('Started altitude updates.')
            	try:
            		while True:
            			pass
            	finally:
            		altimeter.stopRelativeAltitudeUpdates()
            		print('Updates stopped.')
            
            if __name__ == '__main__':
            	main()
            
            Phuket2 1 Reply Last reply Reply Quote 1
            • omz
              omz last edited by

              I'm a caver hobbyist myself, and want to see whether sensors in phones can aid underground spatial orientation. (GPS obviously doesn't work underground!)

              That's a pretty awesome use case btw!

              1 Reply Last reply Reply Quote 3
              • Phuket2
                Phuket2 @omz last edited by

                @omz , is this a dangerous example. I mean for battery life. Eg is it like the motion module. That if you don't actually call the stop update method, it will use extra battery. I am not sure what context that is in. No pun intended. But can that example be used with a context manager, or maybe it does not matter. I am not sure. Just going off what I read before from the Pythonista modules for hardware access. Maybe it's different when doing it this way

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

                  @Phuket2 Well, you'd need to stop the updates at some point (and I'm doing that in the example). I'm not sure how much altimeter updates drain the battery; I suspect that it's actually not very much with the M8/M9 motion co-processor all these devices have.

                  But even if you forget to stop the updates, iOS will suspend the app after a couple of minutes anyway, if it's not in the foreground, so you can't really drain the battery very much while you're not actively using the app.

                  Phuket2 1 Reply Last reply Reply Quote 0
                  • Phuket2
                    Phuket2 @omz last edited by

                    @omz , ok perfect. I wasn't sure how global the settings were. Btw, if I stop the script, I don't get the 'Updates stopped" print.

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

                      Btw, if I stop the script, I don't get the 'Updates stopped" print.

                      @Phuket2 Hmm, that's weird. Are you using Pythonista 2 or 3?

                      Phuket2 1 Reply Last reply Reply Quote 0
                      • Phuket2
                        Phuket2 @omz last edited by

                        @omz , sorry I was wrong it does print the stop msg. Not sure what I did wrong. I recopied the script from here and it worked as you described . I thought I was being attentive , but apparently not 😱
                        It was Pythonista 2. Again sorry, hate to waste your time

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

                          I am sure that @tszheichoi takes an extra flashlight when spelunking just in case the iPhone batteries are drained!

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

                            I am not used to ObjC stuff. Is there an easy way to get a single barometer reading from the sensor?

                            mikael 1 Reply Last reply Reply Quote 0
                            • mikael
                              mikael @victordomingos last edited by

                              @victordomingos, this Apple API only gives you relative readings, not one absolute value. Thus it seems that one single call would not be very useful?

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

                                ... but of course you have the pressure value there. Here’s a modification that gives you a simple get_pressure function (a bit of a hack because of the global variable use).

                                from objc_util import ObjCInstance, ObjCClass, ObjCBlock, c_void_p
                                
                                pressure = None
                                
                                def get_pressure():
                                  
                                  def handler(_cmd, _data, _error):
                                    global pressure
                                    pressure = ObjCInstance(_data).pressure()
                                
                                  handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p, c_void_p, c_void_p])
                                
                                  CMAltimeter = ObjCClass('CMAltimeter')
                                  NSOperationQueue = ObjCClass('NSOperationQueue')
                                  if not CMAltimeter.isRelativeAltitudeAvailable():
                                    print('This device has no barometer.')
                                    return
                                  altimeter = CMAltimeter.new()
                                  main_q = NSOperationQueue.mainQueue()
                                  altimeter.startRelativeAltitudeUpdatesToQueue_withHandler_(main_q, handler_block)
                                  #print('Started altitude updates.')
                                  try:
                                    while pressure is None:
                                      pass
                                  finally:
                                    altimeter.stopRelativeAltitudeUpdates()
                                    #print('Updates stopped.')
                                    return pressure
                                
                                if __name__ == '__main__':
                                  print(get_pressure())
                                
                                1 Reply Last reply Reply Quote 0
                                • victordomingos
                                  victordomingos last edited by

                                  What kind of value (units) is this last version of the script printing out?

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

                                    timestamp (an NSTimeInterval in seconds since the device has been booted)
                                    relativeAltitude (an NSNumber in meters)
                                    pressure (an NSNumber in kilopascal)

                                    1 Reply Last reply Reply Quote 1
                                    • DaveClark
                                      DaveClark last edited by

                                      I want to use the NSNumber for pressure in a calculation. How do I convert it to something I can use with mathematical functions?

                                      mikael 1 Reply Last reply Reply Quote 0
                                      • mikael
                                        mikael @DaveClark last edited by

                                        @DaveClark, change return pressure on line 28 to return pressure.CGFloatValue().

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

                                          That did it and now I know I need to read the documents more. Thanks you for your help

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

                                            It was working after I change line 28 to your suggestion. But today without changing anything(I think)

                                            line 28 was return pressure

                                            line 28 now return pressure.CGFloatValue()

                                            Now it is showing an error message complaining about line 28. It says:

                                            AttributeError
                                            no method found for
                                            CGFloatValue

                                            again, I am at a loss

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors