1. *** New version of B4J is available ***
    B4J v7.8
    Dismiss Notice

iOS Question Can someone help me convert my B4A code to B4I?

Discussion in 'iOS Questions' started by Wolli013, Jul 21, 2019.

  1. Wolli013

    Wolli013 Active Member Licensed User

    Can someone help me convert my B4A code to B4I?
    A 1 to 1 conversion doesn't work because B4I probably asks for it differently.
    Here is my code that runs in B4A. Bluetooth sensors are read out.

    Code:
    Sub Manager_DeviceFound (Name As StringId As String, AdvertisingData As Map, RSSI As Double)
    Dim bc As ByteConverter
    Dim key As Int = -1 'type is important. Must be Int.
    If AdvertisingData.ContainsKey(key) Then

    Dim b() As Byte = AdvertisingData.Get(key)
    Dim hex As String = bc.HexFromBytes(b)

    'Temperatur
    Private temperature As Int
    Private tem1,tem2,hum As Int
    Private temp1,hum1 As Float
    Dim temperatureSign As Boolean = Bit.And(b(4), 0x80) <> 0
    temperature = 
    Bit.And(b(4), 0x7f)' + (b(5) / 100.0)
        If temperatureSign Then
        temperature = -temperature
        
    End If
    tem1 = temperature
    tem2 = b(
    5)

    'Luftfeuchtigkeit
        Dim Str3 As String
         Str3 = hex.SubString2(
    68)
          hum = 
    Bit.ParseInt(Str3, 16)
    'Ergebniss
        temp1 = tem1&"."&tem2 ' = Grad
        hum1 = hum/2 ' = Relative Luftfeuchtigkeit
    End If

    End Sub
    Hier noch ein Auszug aus dem SwiftCode

    Code:
    class DecodeFormat3: RuuviTagDecoder {
        func decode(data: Data) -> RuuviTag {
            let ruuviTag = RuuviTag()
           
            ruuviTag.humidity = Double(data[
    3]) * 0.5
           
            let temperatureSign = (data[
    4] >> 7) & 1
            let temperatureBase = data[
    4] & 0x7F
            let temperatureFraction = Double(data[
    5]) / 100.0
            var temperature = Double(temperatureBase) + temperatureFraction
            
    if (temperatureSign == 1) {
                temperature *= -
    1;
            
    }
            ruuviTag.temperature = temperature
           
            let pressureHi = data[6] & 0xFF
            let pressureLo = data[7] & 0xFF
            ruuviTag.pressure = Double(pressureHi) * 256.0 + 50000.0 + Double(pressureLo)
            ruuviTag.pressure /= 100.0;
           
            ruuviTag.accelerationX = Double(UInt16(data[8]) << 8 | UInt16(data[9] & 0xFF)) / 1000.0;
            ruuviTag.accelerationY = Double(UInt16(data[10]) << 8 | UInt16(data[11] & 0xFF)) / 1000.0;
            ruuviTag.accelerationZ = Double(UInt16(data[12]) << 8 | UInt16(data[13] & 0xFF)) / 1000.0;
           
            let battHi = data[14] & 0xFF;
            let battLo = data[15] & 0xFF;
            ruuviTag.voltage = (Double(battHi) * 256.0 + Double(battLo)) / 1000.0;
           
            ruuviTag.updatedAt = NSDate()
            return ruuviTag
        }
    }
     
  2. Erel

    Erel Administrator Staff Member Licensed User

    Where is the failing B4i code? What have you tried? It should be very similar to the B4A code.
     
  3. Wolli013

    Wolli013 Active Member Licensed User

    Code:
    Dim bc As ByteConverter
    Dim key As Int = -1 'type is important. Must be Int.
    'If AdvertisingData.ContainsKey(key) Then

    Dim b() As Byte = AdvertisingData.Get(key)
    Dim hex As String = bc.HexFromBytes(b)

    'Temperatur
    Private temperature As Int
    Private tem1,tem2,hum As Int
    Private temp1,hum1 As Float

    1081Dim temperatureSign As Boolean = Bit.And(b(4), 0x80) <> 0

    temperature = 
    Bit.And(b(4), 0x7f)' + (b(5) / 100.0)
        If temperatureSign Then
        temperature = -temperature
        
    End If
    tem1 = temperature
    tem2 = b(
    5)

    'Luftfeuchtigkeit
        Dim Str3 As String
         Str3 = hex.SubString2(
    68)
          hum = 
    Bit.ParseInt(Str3, 16)
    'Ergebniss
        temp1 = tem1&"."&tem2 ' = Grad
        hum1 = hum/2 ' = Relative Luftfeuchtigkeit
    'End If

    Error occurred on line: 1081 (Main)
    Target is null. Method called: getByteFast:
    Stack Trace: (
    CoreFoundation <redacted> + 252
    libobjc.A.dylib objc_exception_throw + 56
    CoreFoundation <redacted> + 0
    Te+[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 192
    Te-[B4IShell runMethod:] + 448
    Te-[B4IShell raiseEventImpl:method:args::] + 1648
    Te-[B4IShellBI raiseEvent:event:params:] + 1580
    Te+[B4IObjectWrapper raiseEvent:::] + 300
    Te-[BleDelegate centralManager:didDiscoverPeripheral:advertisementData:RSSI:] + 552
    CoreBluetooth <redacted> + 1060
    CoreBluetooth <redacted> + 620
    CoreBluetooth <redacted> + 60
    libdispatch.dylib <redacted> + 24
    libdispatch.dylib <redacted> + 16
    libdispatch.dylib <redacted> + 592
    libdispatch.dylib <redacted> + 480
    libdispatch.dylib <redacted> + 784
    CoreFoundation <redacted> + 12
    CoreFoundation <redacted> + 1924
    CoreFoundation CFRunLoopRunSpecific + 436
    GraphicsServices GSEventRunModal + 104
    UIKitCore UIApplicationMain + 212
    Temain + 124
    libdyld.dylib <redacted> + 4
    )
     
  4. Wolli013

    Wolli013 Active Member Licensed User

    And s I have also tried it only there fit then the temperature values do not ansimsten it goes.

    Code:
    Log("LogString: " & AdvertisingData.Get("kCBAdvDataManufacturerData"))
      
       
    Dim LogString As String = AdvertisingData.Get("kCBAdvDataManufacturerData")
       
    Log("LogString1: " & LogString.SubString2(1, LogString.Length-1))
      
       LogString = LogString.SubString2(
    1, LogString.Length-1).Replace(" """)
       
    Log("LogString2: " & LogString)

     
            
    Log("Scanne Sensor 1")
            
    Dim bc As ByteConverter   
            
     
     
    Dim temperature As Int
     
    Private tem1,tem2,hum As Int
     
    Private temp1,temp2,hum1 As Float
        
    Dim temperatureSign As Boolean = Bit.And(LogString.SubString2(810), 0x80) <> 0
    temperature = 
    Bit.And(LogString.SubString2(810), 0x7f)' + (b(5) / 100.0)
    If temperatureSign Then
    temperature = -temperature
    End If
    tem1 = temperature
    tem2 = LogString.SubString2(
    1011)
     
           
    Dim Str3 As String 
               Str3 = LogString.SubString2(
    68)  '1 0 ... 200     Humidity (one lsb Is 0.5%, e.g. 128 Is 64%)
     
     
    'Luftfeuchtigkeit
     hum = Bit.ParseInt(Str3, 16)
     
             temp1 = tem1&
    "."&tem2 ' = Grad
     
              hum1 = hum/
    2 ' = Relative Luftfeuchtigkeit
     
  5. Erel

    Erel Administrator Staff Member Licensed User

    What is the output of Log(AdvertisingData)?
     
  6. Wolli013

    Wolli013 Active Member Licensed User

    (read only map) {
    kCBAdvDataIsConnectable = 0;
    kCBAdvDataManufacturerData = <990403c5 1320c6f8 00fe03d8 000c0b89>;
     
  7. Erel

    Erel Administrator Staff Member Licensed User

    Are you able to get the manufacturer data?
    Code:
    Log(GetType(AdvertisingData.Get("kCBAdvDataManufacturerData"))
    Log("LogString: " & AdvertisingData.Get("kCBAdvDataManufacturerData"))
     
  8. Wolli013

    Wolli013 Active Member Licensed User

    _NSInlineData
    LogString: <9904037e 171cc664 03ec0118 fffc0a81>
     
  9. Erel

    Erel Administrator Staff Member Licensed User

    A bit hacky but try this:
    Code:
    Dim s As String = AdvertisingData.Get("kCBAdvDataManufacturerData")
    s = s.SubString2(
    1, s.Length - 1)
    Dim bc As ByteConverter
    Dim b() As Byte = bc.HexToBytes(s)
     
  10. Wolli013

    Wolli013 Active Member Licensed User

    Code:
    Dim s As String = AdvertisingData.Get("kCBAdvDataManufacturerData")
    s = s.SubString2(
    1, s.Length - 1)
    Dim bc As ByteConverter
    1076Dim b() As Byte = bc.HexToBytes(s)

    Dim hex As String = bc.HexFromBytes(b)

    'Temperatur
    Private temperature As Int
    Private tem1,tem2,hum As Int
    Private temp1,hum1 As Float
    Dim temperatureSign As Boolean = Bit.And(b(4), 0x80) <> 0
    temperature = 
    Bit.And(b(4), 0x7f)' + (b(5) / 100.0)
        If temperatureSign Then
        temperature = -temperature
        
    End If
    tem1 = temperature
    tem2 = b(
    5)

    'Luftfeuchtigkeit
        Dim Str3 As String
         Str3 = hex.SubString2(
    68)
          hum = 
    Bit.ParseInt(Str3, 16)
    'Ergebniss
        temp1 = tem1&"."&tem2 ' = Grad
        hum1 = hum/2 ' = Relative Luftfeuchtigkeit
    Error occurred on line: 1076 (Main)
    -[__NSCFString characterAtIndex:]: Range or index out of bounds
    Stack Trace: (
    CoreFoundation <redacted> + 252
    libobjc.A.dylib objc_exception_throw + 56
    CoreFoundation <redacted> + 0
    CoreFoundation <redacted> + 112
    Te-[B4IByteConverter HexToBytes:] + 192
    CoreFoundation <redacted> + 144
    CoreFoundation <redacted> + 292
    Te+[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1624
    Te-[B4IShell runMethod:] + 448
    Te-[B4IShell raiseEventImpl:method:args::] + 1648
    Te-[B4IShellBI raiseEvent:event:params:] + 1580
    Te+[B4IObjectWrapper raiseEvent:::] + 300
    Te-[BleDelegate centralManager:didDiscoverPeripheral:advertisementData:RSSI:] + 552
    CoreBluetooth <redacted> + 1060
    CoreBluetooth <redacted> + 620
    CoreBluetooth <redacted> + 60
    libdispatch.dylib <redacted> + 24
    libdispatch.dylib <redacted> + 16
    libdispatch.dylib <redacted> + 592
    libdispatch.dylib <redacted> + 480
    libdispatch.dylib <redacted> + 784
    CoreFoundation <redacted> + 12
    CoreFoundation <redacted> + 1924
    CoreFoundation CFRunLoopRunSpecific + 436
    GraphicsServices GSEventRunModal + 104
    UIKitCore UIApplicationMain + 212
    Temain + 124
    libdyld.dylib <redacted> + 4
    )
     
  11. Erel

    Erel Administrator Staff Member Licensed User

    Code:
    s = s.SubString2(1, s.Length - 1).Replace(" """)
    log(s)
    Dim b() As Byte = bc.HexToBytes(s)
     
  12. Wolli013

    Wolli013 Active Member Licensed User

    runs partially

    Code:
    Dim bc As ByteConverter
    Dim s As String = AdvertisingData.Get("kCBAdvDataManufacturerData")
    s = s.SubString2(
    1, s.Length - 1).Replace(" """)
    Log(s)
    Dim b() As Byte = bc.HexToBytes(s)

    Dim hex As String = bc.HexFromBytes(b)

    'Temperatur
    Private temperature As Int
    Private tem1,tem2,hum As Int
    Private temp1,hum1 As Float

    1087:Dim temperatureSign As Boolean = Bit.And(b(4), 0x80) <> 0

    temperature = 
    Bit.And(b(4), 0x7f)' + (b(5) / 100.0)
        If temperatureSign Then
        temperature = -temperature
        
    End If
    tem1 = temperature
    tem2 = b(
    5)

    'Luftfeuchtigkeit
        Dim Str3 As String
         Str3 = hex.SubString2(
    68)
          hum = 
    Bit.ParseInt(Str3, 16)
    'Ergebniss
        temp1 = tem1&"."&tem2 ' = Grad
        hum1 = hum/2 ' = Relative Luftfeuchtigkeit
    Error occurred on line: 1087 (Main)
    Out of bounds. Index=4 Length=1
     
  13. Erel

    Erel Administrator Staff Member Licensed User

    Help us help you. What is the output of Log(s)?

    Put a breakpoint on that line. What is the length of b?
     
  14. Wolli013

    Wolli013 Active Member Licensed User

    Log(s)
    9904037a184ac72a0036fff104160bbf

    Without error
     
    Last edited: Jul 21, 2019
  15. Wolli013

    Wolli013 Active Member Licensed User

    Log(s)
    ul

    with Error

    Error occurred on line: 1087 (Main)
    Out of bounds. Index=4 Length=1
    Stack Trace: (
    CoreFoundation <redacted> + 252
    libobjc.A.dylib objc_exception_throw + 56
    CoreFoundation <redacted> + 0
    Te-[B4IArray getByteFast:] + 224
    CoreFoundation <redacted> + 144
    CoreFoundation <redacted> + 292
    Te+[B4I runDynamicMethod:method:throwErrorIfMissing:args:] + 1624
    Te-[B4IShell runMethod:] + 448
    Te-[B4IShell raiseEventImpl:method:args::] + 1648
    Te-[B4IShellBI raiseEvent:event:params:] + 1580
    Te+[B4IObjectWrapper raiseEvent:::] + 300
    Te-[BleDelegate centralManager:didDiscoverPeripheral:advertisementData:RSSI:] + 552
    CoreBluetooth <redacted> + 1060
    CoreBluetooth <redacted> + 620
    CoreBluetooth <redacted> + 60
    libdispatch.dylib <redacted> + 24
    libdispatch.dylib <redacted> + 16
    libdispatch.dylib <redacted> + 592
    libdispatch.dylib <redacted> + 480
    libdispatch.dylib <redacted> + 784
    CoreFoundation <redacted> + 12
    CoreFoundation <redacted> + 1924
    CoreFoundation CFRunLoopRunSpecific + 436
    GraphicsServices GSEventRunModal + 104
    UIKitCore UIApplicationMain + 212
    Temain + 124
    libdyld.dylib <redacted> + 4
    )
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    I'm sorry but I don't understand anything from these posts.


    Works fine here:
    Code:
    Dim s As String = "9904037a184ac72a0036fff104160bbf"
    Dim bc As ByteConverter
    Dim b() As Byte = bc.HexToBytes(s)
    Log(b.Length)
    Dim temperatureSign As Boolean = Bit.And(b(4), 0x80) <> 0
    Log(temperatureSign)
    Use the debugger to better understand the values.
     
    Wolli013 likes this.
  17. Erel

    Erel Administrator Staff Member Licensed User

    If s = "ul" then it is not the value that you expect.
     
    Wolli013 likes this.
  18. Wolli013

    Wolli013 Active Member Licensed User

    I'm probably getting something that doesn't belong there.
    But I will find out.
    Many, many thanks for your help.
    I've made a lot of progress and now I can do the rest on my own.
    Have a nice Sunday.
    I love B4A and B4I
     
  19. emexes

    emexes Well-Known Member Licensed User

    I started off converting your Swift code to B4A for fun, using a SInt8ToUInt16 sub, but then I decided to just do it line by line with no library. Probably too late, but perhaps there might be some stuff that is useful.

    Btw I am a bit sus about the temperature fraction being in 0.01 (decimal) rather than 0.00000001 (binary), but given that other scalings are decimal, perhaps it is ok.

    Code:
    Sub Process_Globals

        
    Type RuuviTagType( _
            Humidity 
    As Double, _
            Temperature 
    As Double, _
            Pressure 
    As Double, _
            AccelerationX 
    As Double, _
            AccelerationY 
    As Double, _
            AccelerationZ 
    As Double, _
            Voltage 
    As Double, _
            UpdatedAt 
    As Long _
        )
       
    End Sub

    Sub DecodeData(Data() As Byte) As RuuviTagType

        
    '''let ruuviTag = RuuviTag()
        Dim RuuviTag As RuuviTagType

        
    If Data.Length < 16 Then
            
    Log("Data(" & Data.Length & ") too short, should be at least 16 bytes")
        
    End If
       
        
    '''RuuviTag.humidity = Double(data[3]) * 0.5
        RuuviTag.Humidity = Data(3) * 0.5
       
        
    '''let temperatureSign = (data[4] >> 7) & 1
        '''let temperatureBase = data[4] & 0x7F
        Dim TemperatureSign As Int = Bit.And(Data(4), 0x80)    'slight deviation here - non-zero means negative
        Dim TemperatureBase As Int = Bit.And(Data(4), 0x7F)
       
        
    '''let temperatureFraction = Double(data[5]) / 100.0
        Dim TemperatureFraction As Double = Data(5) / 100    'decimal fraction? not binary? or 16-bit int scaled by 0.01?
       
        
    '''var Temperature = Double(temperatureBase) + TemperatureFraction
        Dim Temperature As Double = TemperatureBase + TemperatureFraction
       
        
    '''If (temperatureSign == 1) {
        '''    Temperature *= -1;
        '''}
        If TemperatureSign <> 0 Then
            Temperature = -Temperature
        
    End If
       
        
    '''RuuviTag.temperature = Temperature
        RuuviTag.Temperature = Temperature    'déjà vu ;-)
       
        
    '''let pressureHi = data[6] & 0xFF
        '''let pressureLo = data[7] & 0xFF
        Dim PressureHi As Int = Bit.And(Data(6), 0xFF)    'high byte first?
        Dim PressureLo As Int = Bit.And(Data(7), 0xFF)
       
        
    '''ruuviTag.pressure = Double(PressureHi) * 256.0 + 50000.0 + Double(pressureLo)
        '''ruuviTag.pressure /= 100.0;
        RuuviTag.Pressure = Bit.Or(Bit.ShiftLeft(PressureHi, 8), PressureLo) + 50000    'offset by 50000?
        RuuviTag.Pressure = RuuviTag.Pressure / 100
       
        
    '''RuuviTag.accelerationX = Double(UInt16(data[8]) << 8 | UInt16(data[9] & 0xFF)) / 1000.0;
        '''RuuviTag.accelerationY = Double(UInt16(data[10]) << 8 | UInt16(data[11] & 0xFF)) / 1000.0;
        '''RuuviTag.accelerationZ = Double(UInt16(data[12]) << 8 | UInt16(data[13] & 0xFF)) / 1000.0;
        RuuviTag.AccelerationX = Bit.Or(Bit.ShiftLeft(Bit.And(Data( 8), 0xFF), 8), Bit.And(Data( 9), 0xFF)) / 1000
        RuuviTag.AccelerationY = 
    Bit.Or(Bit.ShiftLeft(Bit.And(Data(10), 0xFF), 8), Bit.And(Data(11), 0xFF)) / 1000
        RuuviTag.AccelerationZ = 
    Bit.Or(Bit.ShiftLeft(Bit.And(Data(12), 0xFF), 8), Bit.And(Data(13), 0xFF)) / 1000
       
        
    '''let battHi = data[14] & 0xFF;
        '''let battLo = data[15] & 0xFF;
        Dim BattHi As Int  = Bit.And(Data(14), 0xFF)
        
    Dim BattLo As Int = Bit.And(Data(15), 0xFF)
       
        
    '''RuuviTag.voltage = (Double(BattHi) * 256.0 + Double(BattLo)) / 1000.0;
        RuuviTag.Voltage = Bit.Or(Bit.ShiftLeft(BattHi, 8), BattLo) / 1000
       
        
    '''RuuviTag.updatedAt = NSDate()
        RuuviTag.UpdatedAt = DateTime.Now
       
        
    Return RuuviTag
       
    End Sub
     
    Wolli013 likes this.
  20. Wolli013

    Wolli013 Active Member Licensed User

    WOW!
    Thank you
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice