Android Question DJI : BatteryState

aeropic

Active Member
Licensed User
Longtime User
Hi all,

After few years of absence, I'm back in the B4A world and I'm trying to play with the DJI library.
The drone example works fine on the Mavic Mini. I wanted to play with batteries and my goal was to develop a very simple application to get in real time the current drawn in different phases of flight.
Unfortunately some key methods are not yet implemented in the B4A library and I"m afraid I don't get the skills to do it alone ;-)
I would be interested in adding the following methods which are present in the DJI API.
Who could explain me (in simple words) the way to do it please ?

Electrical
method
getVoltage


method
getCurrent

Thanks
 

aeropic

Active Member
Licensed User
Longtime User
It's now working !!!! So cool I can get the current in real time.
As you may see I screwed something at video level but that's another topic ;-)
Thanks a lot Erel for this nice library.

Screenshot_20210205-192914.jpg

B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region

'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip

Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private sdk As DJISDKManager
    Private timer1 As Timer
    Private aircraft As DJIAircraft
    
    Private controller As DJIFlightController
    Private camera As DJICamera
    Private aircraftName As String
    Private batteryLevel As Int
    Private voltage As Int
    Private current As Int
    Private IMU As String
    Private pws As PhoneWakeState
    Private HotpointOperator As DJIHotpointMissionOperator
    Private MissionStatus As String
    Private pnlCamera As B4XView
    Private lblText As B4XView
    Private btnStartMission As B4XView
    Private btnStopMission As B4XView
    Private rp As RuntimePermissions
End Sub

Public Sub Initialize
    
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("1")
    Wait For (RequestPermissions) Complete (Result As Boolean)
    If Result Then
        sdk.Initialize("sdk")
        timer1.Initialize("timer1", 200)
        Wait For SDK_RegisteredResult (Success As Boolean, ErrorMessage As String)
        If Success Then
            Log("Registered successfully!")
            Log("activation state: " & sdk.ActivationState)
            Log("binding state: " & sdk.AircraftBindingState)
            sdk.StartConnectionToProduct
        Else
            Log(ErrorMessage)
        End If
    Else
        ToastMessageShow("No permission granted!", True)
    End If
End Sub

Private Sub RequestPermissions As ResumableSub
    rp.CheckAndRequest(rp.PERMISSION_ACCESS_FINE_LOCATION)
    Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean)
    If Result = False Then Return False
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean)
    If Result = False Then Return False
    rp.CheckAndRequest(rp.PERMISSION_READ_PHONE_STATE)
    Wait For B4XPage_PermissionResult (Permission As String, Result As Boolean)
    Return Result
End Sub

Sub SDK_ActivationStateChanged (State As String)
    Log("Activation state changed: " & State)
End Sub

Sub SDK_BindingStateChanged (State As String)
    Log($"SDK_BindingStateChanged: ${State}"$)
    If (State = "BOUND" Or State = "NOT_REQUIRED") And aircraft <> Null And aircraft.Connected Then
        AfterAircraftConnected
    Else
        Log("Aircraft disconnected!")
        lblText.Text = $"Disconnected!!!"$
        timer1.Enabled = False
    End If
End Sub

Sub SDK_ProductConnected (AircraftData As Object)
    If AircraftData <> Null Then
        Log("Product connected")
        aircraft.Initialize("aircraft", AircraftData)
        If aircraft.Connected Then
            AfterAircraftConnected
        End If
    Else
        Log("No connected product")
    End If
End Sub

Sub SDK_ProductDisconnected
    Log("Product disconnected")
End Sub



Sub Aircraft_BatteryState (battery As Object, RemainingPercentage As Int)
    batteryLevel = RemainingPercentage
    Dim jo As JavaObject = battery
    voltage  = jo.RunMethod("getVoltage", Null)
    current  = jo.RunMethod("getCurrent", Null)
End Sub

Sub AfterAircraftConnected
    Log("AfterAircraftConnected")
    If aircraft.CameraReady = False Or aircraft.BatteryReady = False Then
        Log("Camera / battery not ready")
        Sleep(500)
        If aircraft.Connected Then AfterAircraftConnected
        Return
    End If
    aircraft.RegisterBatteryStateEvent
    controller.Initialize("controller", aircraft)
    CreateHardwareStateListener
    Log($"simulator: ${controller.SimulatorStarted)}"$
    camera.Initialize("camera", aircraft)
    pnlCamera.AddView(camera.CreateVideoView, 0, 0, pnlCamera.Width, pnlCamera.Height)
    timer1.Enabled = True
    HotpointOperator.Initialize("HotpointOperator")
    aircraftName = "N/A"
    Wait for (aircraft.GetName) Aircraft_ResultWithValue (Success As Boolean, ErrorMessage As String, Value As Object)
    If Success Then
        aircraftName = Value
    End If
End Sub

Sub CreateHardwareStateListener
    Dim RemoteController As JavaObject = aircraft
    RemoteController = RemoteController.RunMethod("getRemoteController", Null)
    Dim callback As Object = RemoteController.CreateEventFromUI("dji.common.remotecontroller.HardwareState$HardwareStateCallback", "HardwareState", Null)
    RemoteController.RunMethod("setHardwareStateCallback", Array(callback))
End Sub

Sub HardwareState_Event (MethodName As String, Args() As Object) As Object
    Dim HardwareState As JavaObject = Args(0)
    Dim c1button As JavaObject = HardwareState.RunMethod("getC1Button", Null)
    Dim IsClicked As Boolean = c1button.RunMethod("isPresent", Null)
    Log($"C1 button: ${IsClicked}"$)
    
    
    
    Return Null
End Sub

Sub RotateGimbal (roll As Float) 'ignore
    Dim aircraftjo As JavaObject = aircraft
    Dim gimbal As JavaObject = aircraftjo.RunMethod("getGimbal", Null)
    If gimbal.IsInitialized Then
        Dim cc As Object = gimbal.CreateEventFromUI("dji.common.util.CommonCallbacks$CompletionCallback", "callback", Null)
        gimbal.RunMethod("rotate", Array(CreateRotation(roll), cc))
        Wait For (gimbal) Callback_Event (MethodName As String, Args() As Object)
        If Args(0) = Null Then
            Log("Gimbal rotated successfully.")
        Else
            Log("Error setting rotation: " & Args(0))
        End If
    Else
        Log("Gimbal not available.")
    End If
    
End Sub

Sub CreateRotation (RollAngle As Float) As JavaObject
    Dim builder As JavaObject
    builder.InitializeNewInstance("dji.common.gimbal.Rotation.Builder", Null)
    Dim time As Double = 2 'seconds
    builder.RunMethod("mode", Array("ABSOLUTE_ANGLE"))
    builder.RunMethod("time", Array(time))
    builder.RunMethod("roll", Array(RollAngle))
    Return builder.RunMethodJO("build", Null)
End Sub

Private Sub B4XPage_Foreground
    pws.KeepAlive(True)
End Sub

Private Sub B4XPage_Background
    pws.ReleaseKeepAlive
End Sub

Sub Timer1_Tick
    If controller.IsInitialized Then
        Dim St As DJIFlightControllerCurrentState = controller.CurrentState
        Dim speed As Double = Sqrt(Power(St.VelocityX, 2) + Power(St.VelocityY, 2))
        Dim sb As CSBuilder
        sb.Initialize
        sb.Append($"Aircraft: ${aircraftName}"$).Append(CRLF)
        SetColor(sb, batteryLevel < 30).Append($"Battery: ${batteryLevel}%"$).Pop.Append(CRLF)
        SetColor(sb, St.GPSStatus <> 4 And St.GPSStatus <> 5).Append($"GPSStatus (5 = good): ${St.GPSStatus}"$).Pop
        sb.Append(CRLF)
        sb.Append($"Simulator: ${controller.SimulatorStarted}
FlightMode: ${St.FlightMode}
Current : ${current}
Voltage : ${voltage}
Altitude: $1.0{St.AircraftLocation.Altitude} m
Location: $1.3{St.AircraftLocation.Latitude} / $1.3{St.AircraftLocation.Longitude}
speed: $1.0{speed} m/s
VelocityZ: $1.1{-St.VelocityZ + 0.001} m/s
HotpointOperator: ${HotpointOperator.MissionState}
Activation: ${sdk.ActivationState}
Binding: ${sdk.AircraftBindingState}
"$)
        AppendIf(sb, St.IMUPreheating, $"IMUPreheating: ${St.IMUPreheating}"$)
        sb.Append(IMU)
        SetColor(sb, St.HomeLocationSet = False)
        If St.HomeLocationSet Then
            sb.Append($"Home: $1.3{St.HomeLocation.Latitude} / $1.3{St.HomeLocation.Longitude}"$)
        Else
            sb.Append("Home: Not set!")
            If St.GPSStatus = 4 Or St.GPSStatus = 5 Then
                SetHome
            End If
        End If
        sb.Pop.Append(CRLF)
        AppendIf(sb, MissionStatus <> "", MissionStatus)
        lblText.Text = sb
    End If
End Sub

Sub SetColor(sb As CSBuilder, Condition As Boolean) As CSBuilder
    If Condition Then sb.Color(Colors.Red) Else sb.Color(Colors.White)
    Return sb
End Sub

Sub AppendIf(sb As CSBuilder, Condition As String, Text As String) As CSBuilder
    If Condition Then sb.Append(Text).Append(CRLF)
    Return sb
End Sub

Sub SetHome
    Wait For (controller.SetHomeLocationUsingAircraftCurrentLocation) Controller_Result (Success As Boolean, ErrorMessage As String)
    If Success Then
        Log("home set")
    Else
        Log("Error: " & ErrorMessage)
    End If
End Sub


Sub Controller_IMUStateChanged (State As DJIIMUState)
    If State.AccelerometerStatus = "" Then Return
    Dim sb As CSBuilder
    sb.Initialize
    AppendIf(sb, State.AccelerometerStatus <> "NORMAL_BIAS", $"Acceleromter: ${State.AccelerometerStatus}"$)
    AppendIf(sb, State.CalibrationStatus <> "NONE", $"Calibration: ${State.CalibrationStatus}"$)
    AppendIf(sb, State.GyroscopeState <> "NORMAL_BIAS", $"Gyroscope: ${State.GyroscopeState}"$)
    IMU = sb
End Sub

Sub btnStartMission_Click
    Dim mission As DJIHotpointMission
    'change coordinates here and remove the ExitApplication
    mission.Initialize(32.836084, 35.268652, 50, 300, 20, "TOWARDS_HOT_POINT")
    Wait For (HotpointOperator.StartMission(mission)) HotpointOperator_Result (Success As Boolean, ErrorMessage As String)
    If Success Then
        Log("Start: " & Success & ", " & ErrorMessage)
        MissionState(True)
    Else
        Log("Error uploading: " & ErrorMessage)
        ToastMessageShow("Error uploading: " & ErrorMessage, True)
    End If
End Sub




Sub HotpointOperator_HotpointMissionStart
    MissionStatus = "MissionStart"
End Sub

Sub HotpointOperator_HotpointMissionFinish (Error As String)
    MissionStatus = "MissionFinish: " & Error
    MissionState(False)
End Sub

Sub MissionState(Running As Boolean)
    btnStartMission.Enabled = Not(Running)
    btnStopMission.Enabled = Running
End Sub

Sub HotpointOperator_HotpointMissionProgress (ExecutionEvent As Object)
    Log(ExecutionEvent)
End Sub


Sub btnStopMission_Click
    Wait For (HotpointOperator.StopMission) HotpointOperator_Result (Success As Boolean, ErrorMessage As String)
    If Success = False Then
        ToastMessageShow("Failed to stop", True)
    Else
        MissionStatus = "Mission stopped"
        MissionState(False)
    End If
End Sub
 
Last edited:
Upvote 0
Top