Using Accounter and Packer

I'm having a problem incorporating the Accounter and Packer processors into my Swift code. I'm studying your version 3.x API for Swift which I understand is a wrapper around your C++ API, but I'm still not able to utilize either the Packer or Accounter. It would be nice if there were more examples in Swift for product developers. Short of that, could you please demonstrate how to implement a data processor type? The following is your code from your Swift tutorial, Section 2.1.2.2. As a valuable example to me and others who may be struggling in this area, could you please respond by adding to this code and incorporating, say, an Accounter? If you could answer me back in this forum with an Accounter code example based upon your code below, it would be most helpful and appreciated. I thank you in advance.

@IBAction func startPressed(sender: AnyObject) {
    let board = device.board
    guard mbl_mw_metawearboard_lookup_module(board, MBL_MW_MODULE_ACCELEROMETER) != MODULE_TYPE_NA else {
        print("No accelerometer")
        return
    }
    let signal = mbl_mw_acc_get_acceleration_data_signal(board)
    mbl_mw_datasignal_subscribe(signal, bridge(obj: self)) { (context, data) in
        let _self: DeviceViewController = bridge(ptr: context!)
        let obj: MblMwCartesianFloat = data!.pointee.valueAs()
        print(obj)
    }
    mbl_mw_acc_enable_acceleration_sampling(board)
    mbl_mw_acc_start(board)
}

@IBAction func stopPressed(sender: AnyObject) {
    let board = device.board
    let signal = mbl_mw_acc_get_acceleration_data_signal(board)
    mbl_mw_acc_stop(board)
    mbl_mw_acc_disable_acceleration_sampling(board)
    mbl_mw_datasignal_unsubscribe(signal)
}

Comments

  • @Les said:
    I'm having a problem incorporating the Accounter and Packer processors into my Swift code. I'm studying your version 3.x API for Swift which I understand is a wrapper around your C++ API, but I'm still not able to utilize either the Packer or Accounter.

    What specifically is unclear about the accounter and packer function signatures?

    This thread has some example code for creating a timer processor:
    https://mbientlab.com/community/discussion/comment/7439/#Comment_7439

  • LesLes
    edited March 6

    Thank you for the reply Eric. Here is my code that fails. Can you tell me what I'm doing wrong?

        func createAccounter() {
            let signal = mbl_mw_acc_get_acceleration_data_signal(device.board)
    
            mbl_mw_dataprocessor_accounter_create_count(signal, bridge(obj: self)) { (context, accounter) in
                let _self : DeviceViewController = bridge(ptr: context!)
                mbl_mw_datasignal_subscribe(accounter, bridge(obj: _self)) { (context, accounter) in
                    let obj: MblMwData = accounter!.pointee.valueAs()
                    // debug:
                    print(obj.extra)     // fails
                }
            }
            mbl_mw_acc_enable_acceleration_sampling(self.device.board)
            mbl_mw_acc_start(self.device.board)
        }
    
  • edited March 6

    Describe the error itself in more detail. A lone comment that says "fails" doesn't give me much time work on.

  • Assertion failed in function doTheParse in MetaWearData.swift in the code below. I never get to my print statement.

        // Generalized flow
        assert(MemoryLayout<T>.size == length)
        switch type_id {
        case MBL_MW_DT_ID_UINT32:
            assert(T.self == UInt32.self)
        case MBL_MW_DT_ID_FLOAT:
            assert(T.self == Float.self)
        case MBL_MW_DT_ID_CARTESIAN_FLOAT:
            assert(T.self == MblMwCartesianFloat.self)
        case MBL_MW_DT_ID_INT32:
            assert(T.self == Int32.self)
        case MBL_MW_DT_ID_BATTERY_STATE:
            assert(T.self == MblMwBatteryState.self)
        case MBL_MW_DT_ID_TCS34725_ADC:
            assert(T.self == MblMwTcs34725ColorAdc.self)
        case MBL_MW_DT_ID_EULER_ANGLE:
            assert(T.self == MblMwEulerAngles.self)
        case MBL_MW_DT_ID_QUATERNION:
            assert(T.self == MblMwQuaternion.self)
        case MBL_MW_DT_ID_CORRECTED_CARTESIAN_FLOAT:
            assert(T.self == MblMwCorrectedCartesianFloat.self)
        case MBL_MW_DT_ID_OVERFLOW_STATE:
            assert(T.self == MblMwOverflowState.self)
        case MBL_MW_DT_ID_SENSOR_ORIENTATION:
            assert(T.self == MblMwSensorOrientation.self)
        case MBL_MW_DT_ID_LOGGING_TIME:
            assert(T.self == MblMwLoggingTime.self)
        case MBL_MW_DT_ID_BTLE_ADDRESS:
            assert(T.self == MblMwBtleAddress.self)
        case MBL_MW_DT_ID_BOSCH_ANY_MOTION:
            assert(T.self == MblMwBoschAnyMotion.self)
        case MBL_MW_DT_ID_CALIBRATION_STATE:
            assert(T.self == MblMwCalibrationState.self)
        case MBL_MW_DT_ID_BOSCH_TAP:
            assert(T.self == MblMwBoschTap.self)
        default:
            fatalError("unknown data type")
        }
        return value.bindMemory(to: T.self, capacity: 1).pointee
    }
    
  • Which assert is failing? What are the values on each side of the comparison?

  • The code fails at the line: assert(MemoryLayout.size == length). The length value is 12. I don't know how to determine what the MemoryLayout.size value is. However, the values of the parameters going into doTheParse(length: length, type_id: type_id, value: value) are length: 12, type_id: MblMwDataTypeId with a rawValue of (UInt32) 2, and value: UnsafeMutableRawPointer? (_rawValue = 0x0000000281804010).

    I'm not sure any of the above is useful information. What I'm really looking for is the correct way to create the accounter and get the count value along with my accelerometer data. If possible, example code would go a long way. Does the createAccounter() code I posted 4 messages back look correct to you? Am I missing something in that code?

    Again, I thank you for your help.

  • As I told Eric, the Xcode error causes a halt at the assert line I provided in the code above with the message:
    "Thread x: Assertion failed," The thread number x varies depending upon activity.

    I'm hoping Eric or someone from Mbientlab can provide sample Swift code for an Accounter that gets the count value along with the accelerometer data.

  • The valueAs line is wrong. Cast it to the actual data type not the wrapper data type. The incorrect typing is causing the assert to fail.

    https://mbientlab.com/cppdocs/latest/accelerometer.html#acceleration-sampling
    https://mbientlab.com/tutorials/Swift.html#data-stream

  • Thank you Eric. I should have pointed out that I knew that casting the valueAs as a MblMwCartesianFloat , as you point out, works in terms of retrieving the x, y and z accelerometer data, However, I'm still stuck with my original question: How do I obtain that data AND the Accounter count number for each such accelerometer sample?

  • edited March 9

    @Les said:
    How do I obtain that data AND the Accounter count number for each such accelerometer sample?

    Getting the count value is explained in the accounter documentation, 2nd section:
    https://mbientlab.com/cppdocs/0/dataprocessor.html#accounter

    You already have sample code for getting the acceleration data.

  • Eric, while I really am most appreciative of your responses, I feel we're going in circles. I've studied all the links you have been providing, even before I made my first post. It's obvious that there are some clear examples in some of the other languages, but the documentation is very, very sparse for Swift. As an aside, our company has purchased over a dozen sensors from MbientLab and we anticipate, upon our product's release, purchasing thousands, or even several orders of magnitude beyond that, for resale. But we clearly are in need of support. While your prompt responses are appreciated, what we are really looking for is an example in Swift, similar to the C++ example you pointed out in this link: https://mbientlab.com/cppdocs/0/dataprocessor.html#accounter . Is that a possibility?

  • edited March 11

    The C++ documentation is the Swift documentation (as well as for Python and Node). These specific SDKs are nothing more than wrappers around the same C++ shared library; every function call and use of a pointer, is the same as shown the C++ documentation.

    In the accounter documentation, the example code shows that you cast the extra pointer to a uint32_t*, then deference the pointer. Do the exact same thing in Swift.

  • For the benefit of others on this board interested in this subject, here is the code I came up with to resolve my issues. If anyone sees any problems with this, please let me know. Thanks!

    func createAccounter() {
        let signal = mbl_mw_acc_get_acceleration_data_signal(device.board)
    
        mbl_mw_dataprocessor_accounter_create_count(signal, bridge(obj: self)) { (context, accounter) in
            let _self : DeviceViewController = bridge(ptr: context!)
    
            mbl_mw_datasignal_subscribe(accounter, bridge(obj: _self)) { (context, data) in
                let xyzValues: MblMwCartesianFloat = data!.pointee.valueAs()
    
                // The Magic:
                let extraRawPointer = UnsafeMutableRawPointer(data!.pointee.extra)
                let extraValue = extraRawPointer!.load(as: UInt32.self)
    
                print ("seq: \(extraValue), x: \(xyzValues.x), y: \(xyzValues.y), z: \(xyzValues.z)")
            }
        }
        mbl_mw_acc_enable_acceleration_sampling(self.device.board)
        mbl_mw_acc_start(self.device.board)
    }
    
Sign In or Register to comment.