#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