├── .gitignore ├── .gitmodules ├── .sbtopts ├── .sbtrc ├── LICENSE.md ├── README.md ├── RELEASE-NOTES.md ├── andropilot ├── .gitignore ├── README.md ├── TODO.md ├── adb-connect.sh ├── adbconnect.sh ├── art │ ├── Icons │ │ ├── Forever_32.png │ │ ├── Forever_48.png │ │ ├── Hexa1__blue_48.png │ │ ├── Hexa2__blue_48.png │ │ ├── Hexa2__red_32.png │ │ ├── Hexa2__red_48.png │ │ ├── Hexa2__yellow_32.png │ │ ├── Hexa2__yellow_48.png │ │ ├── Land_32.png │ │ ├── Land_48.png │ │ ├── Number_32.png │ │ ├── Number_48.png │ │ ├── Quad1_blue_32.png │ │ ├── Quad1_blue_48.png │ │ ├── Quad1_red_32.png │ │ ├── Quad1_red_48.png │ │ ├── Quad1_yellow_32.png │ │ ├── Quad1_yellow_48.png │ │ ├── Quad2_blue_32.png │ │ ├── Quad2_blue_48.png │ │ ├── Quad2_red_32.png │ │ ├── Quad2_red_48.png │ │ ├── Quad2_yellow_32.png │ │ ├── Quad2_yellow_48.png │ │ ├── RTL_32.png │ │ ├── RTL_48.png │ │ ├── TakeOff_32.png │ │ ├── TakeOff_48.png │ │ ├── Timed_32.png │ │ ├── Timed_48.png │ │ ├── waypoint_dot_32.png │ │ └── waypoint_dot_48.png │ ├── airplane-48x48.png │ ├── altimeter-icon-28x48.png │ ├── altimeter-icon.png │ ├── arrow.svg │ ├── checklist.png │ ├── droneshare-taskbar.png │ ├── feature-graphic-1024x500.png │ ├── in-flight.svg │ ├── joysticks-10inch.png │ ├── new-ui-wip-no-sidebar.png │ ├── new-ui-wip-sidebar.png │ ├── new-ui-wip.png │ ├── paper-airplane-128x128.png │ ├── paper-airplane-16x16.png │ ├── paper-airplane-180x120.png │ ├── paper-airplane-512x512.png │ ├── paper-airplane-75x75.png │ ├── paper-airplane.svg │ ├── read-only-mode.png │ ├── screenshot-1.png │ ├── screenshot-10inch-copterfence.png │ ├── screenshot-10inch-portrait.png │ ├── screenshot-2.png │ ├── screenshot-3.png │ ├── screenshot-4.png │ ├── screenshot-fence.png │ ├── screenshot-hud.png │ ├── screenshot-landscape.png │ ├── screenshot-overview.png │ ├── screenshot-parameters.png │ ├── screenshot-phone-joystick.png │ ├── screenshot-phone-wp.png │ ├── screenshot-portrait.png │ ├── screenshot-waypoint.png │ └── waypoint-crosshair.svg ├── build.sbt ├── config │ └── application.conf ├── display-debug-cert.sh ├── display-release-cert.sh ├── lib │ ├── FlurryAgent.jar │ ├── aws-android-sdk-1.4.6-core.jar │ ├── aws-android-sdk-1.4.6-s3.jar │ ├── bugsense-3.5.jar │ ├── d2xx.jar │ ├── google-play-services.jar │ ├── logback-android-1.0.7-1.jar │ ├── pebble-kit.jar │ └── usb-serial-for-android-snapshot.jar ├── logcat.sh ├── proguard-android.txt ├── proguard.cfg ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── logback.xml │ │ │ ├── testdata.igc │ │ │ └── webapp │ │ ├── java │ │ │ └── com │ │ │ │ ├── bvcode │ │ │ │ └── ncopter │ │ │ │ │ ├── comms │ │ │ │ │ ├── BluetoothModule.java.disabled │ │ │ │ │ ├── CommunicationClient.java.disabled │ │ │ │ │ ├── CommunicationService.java.disabled │ │ │ │ │ ├── DeviceListActivity.java │ │ │ │ │ └── ICommunicationModule.java │ │ │ │ │ └── widgets │ │ │ │ │ ├── DoubleNumberPicker.java │ │ │ │ │ ├── HUD.java │ │ │ │ │ ├── MinMaxCurrentSlider.java │ │ │ │ │ ├── NumberPicker.java │ │ │ │ │ ├── NumberPickerButton.java │ │ │ │ │ └── ScopeDisplay.java │ │ │ │ └── geeksville │ │ │ │ └── android │ │ │ │ ├── AndroidJUtil.java │ │ │ │ └── PlayTools.java │ │ ├── res │ │ │ ├── drawable-hdpi │ │ │ │ ├── quad_blue.png │ │ │ │ ├── quad_red.png │ │ │ │ ├── quad_yellow.png │ │ │ │ ├── waypoint_dot.png │ │ │ │ ├── waypoint_forever.png │ │ │ │ ├── waypoint_land.png │ │ │ │ ├── waypoint_number.png │ │ │ │ ├── waypoint_rtl.png │ │ │ │ ├── waypoint_takeoff.png │ │ │ │ └── waypoint_timed.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── arrow.png │ │ │ │ ├── blue.png │ │ │ │ ├── blue_dot.png │ │ │ │ ├── flag.png │ │ │ │ ├── hospitals.png │ │ │ │ ├── icon.png │ │ │ │ ├── in_flight.png │ │ │ │ ├── lz_blue.png │ │ │ │ ├── lz_red.png │ │ │ │ ├── lz_yellow.png │ │ │ │ ├── plane_blue.png │ │ │ │ ├── plane_red.png │ │ │ │ ├── plane_yellow.png │ │ │ │ ├── quad_blue.png │ │ │ │ ├── quad_red.png │ │ │ │ ├── quad_yellow.png │ │ │ │ ├── rangerstation.png │ │ │ │ ├── red.png │ │ │ │ ├── waypoint.png │ │ │ │ ├── waypoint_dot.png │ │ │ │ ├── waypoint_forever.png │ │ │ │ ├── waypoint_land.png │ │ │ │ ├── waypoint_number.png │ │ │ │ ├── waypoint_rtl.png │ │ │ │ ├── waypoint_takeoff.png │ │ │ │ ├── waypoint_timed.png │ │ │ │ └── yellow.png │ │ │ ├── drawable-nodpi │ │ │ │ └── watch.png │ │ │ ├── drawable │ │ │ │ ├── arrow.png │ │ │ │ ├── blue.png │ │ │ │ ├── blue_dot.png │ │ │ │ ├── custombutton.xml │ │ │ │ ├── flag.png │ │ │ │ ├── hospitals.png │ │ │ │ ├── icon.png │ │ │ │ ├── in_flight.png │ │ │ │ ├── lz_blue.png │ │ │ │ ├── lz_red.png │ │ │ │ ├── lz_yellow.png │ │ │ │ ├── my_border.xml │ │ │ │ ├── my_border_transparent.xml │ │ │ │ ├── plane_blue.png │ │ │ │ ├── plane_red.png │ │ │ │ ├── plane_yellow.png │ │ │ │ ├── rangerstation.png │ │ │ │ ├── red.png │ │ │ │ ├── rounded_textbackground.xml │ │ │ │ ├── square_textbackground.xml │ │ │ │ ├── timepicker_down_btn.xml │ │ │ │ ├── timepicker_down_disabled.9.png │ │ │ │ ├── timepicker_down_disabled_focused.9.png │ │ │ │ ├── timepicker_down_normal.9.png │ │ │ │ ├── timepicker_down_pressed.9.png │ │ │ │ ├── timepicker_down_selected.9.png │ │ │ │ ├── timepicker_input.xml │ │ │ │ ├── timepicker_input_disabled.9.png │ │ │ │ ├── timepicker_input_normal.9.png │ │ │ │ ├── timepicker_input_pressed.9.png │ │ │ │ ├── timepicker_input_selected.9.png │ │ │ │ ├── timepicker_up_btn.xml │ │ │ │ ├── timepicker_up_disabled.9.png │ │ │ │ ├── timepicker_up_disabled_focused.9.png │ │ │ │ ├── timepicker_up_normal.9.png │ │ │ │ ├── timepicker_up_pressed.9.png │ │ │ │ ├── timepicker_up_selected.9.png │ │ │ │ ├── waypoint.png │ │ │ │ └── yellow.png │ │ │ ├── layout-w480dp-port │ │ │ │ └── main.xml │ │ │ ├── layout-w480dp │ │ │ │ └── main.xml │ │ │ ├── layout-w720dp-port │ │ │ │ └── main.xml │ │ │ ├── layout │ │ │ │ ├── device_list.xml │ │ │ │ ├── device_name.xml │ │ │ │ ├── double_number_picker.xml │ │ │ │ ├── hud_fragment.xml │ │ │ │ ├── joystick_overlay.xml │ │ │ │ ├── main.xml │ │ │ │ ├── map_overlay.xml │ │ │ │ ├── map_with_overlay.xml │ │ │ │ ├── min_max_current_slider.xml │ │ │ │ ├── mini_overview.xml │ │ │ │ ├── modal_bar.xml │ │ │ │ ├── number_picker.xml │ │ │ │ ├── pager_layout.xml │ │ │ │ ├── param_edit.xml │ │ │ │ ├── paramedit_fragment.xml │ │ │ │ ├── parameter_pane.xml │ │ │ │ ├── parameter_row.xml │ │ │ │ ├── progress_list.xml │ │ │ │ ├── rcchannel_row.xml │ │ │ │ ├── simple_list_item_1_small.xml │ │ │ │ ├── splash_fragment.xml │ │ │ │ ├── statusmsg_fragment.xml │ │ │ │ ├── vehicle_overview.xml │ │ │ │ ├── waypoint_row.xml │ │ │ │ └── web_fragment.xml │ │ │ ├── menu │ │ │ │ ├── action_bar.xml │ │ │ │ ├── context_menu.xml │ │ │ │ └── waypoint_menu.xml │ │ │ ├── values-v11 │ │ │ │ └── styles.xml │ │ │ ├── values-v14 │ │ │ │ └── styles.xml │ │ │ ├── values │ │ │ │ ├── arrays.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── strings-spoken.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── xml │ │ │ │ ├── device_filter.xml │ │ │ │ ├── preferences.xml │ │ │ │ ├── preferences_flight.xml │ │ │ │ ├── preferences_mavlink.xml │ │ │ │ ├── preferences_network.xml │ │ │ │ ├── preferences_serial.xml │ │ │ │ └── preferences_share.xml │ │ └── scala │ │ │ └── com │ │ │ └── geeksville │ │ │ ├── andropilot │ │ │ ├── AccessGrantedReceiver.scala │ │ │ ├── AndroidAkkaLogger.scala │ │ │ ├── AndropilotPrefs.scala │ │ │ ├── FlurryClient.scala │ │ │ ├── MyApplication.scala │ │ │ ├── MyBackupAgent.scala │ │ │ ├── UsesDirectories.scala │ │ │ ├── gui │ │ │ │ ├── AndroServiceFragment.scala │ │ │ │ ├── AndroServicePage.scala │ │ │ │ ├── HudFragment.scala │ │ │ │ ├── JoystickController.scala │ │ │ │ ├── JoystickHID.scala │ │ │ │ ├── JoystickView.scala │ │ │ │ ├── LayoutFragment.scala │ │ │ │ ├── ListAdapterHelper.scala │ │ │ │ ├── MainActivity.scala │ │ │ │ ├── ModalFragment.scala │ │ │ │ ├── MyMapFragment.scala │ │ │ │ ├── NotificationIds.scala │ │ │ │ ├── OverviewFragment.scala │ │ │ │ ├── ParameterEditorFragment.scala │ │ │ │ ├── ParameterInfoFragment.scala │ │ │ │ ├── ParameterListFragment.scala │ │ │ │ ├── ParameterPane.scala │ │ │ │ ├── ProgressList.scala │ │ │ │ ├── RadioTools.scala │ │ │ │ ├── RcChannelsFragment.scala │ │ │ │ ├── ServoOutputFragment.scala │ │ │ │ ├── SettingsActivity.scala │ │ │ │ ├── SimpleListFragment.scala │ │ │ │ ├── SplashFragment.scala │ │ │ │ ├── StatusMsgFragment.scala │ │ │ │ ├── SunspotDetectorTask.scala │ │ │ │ ├── WaypointActionMode.scala │ │ │ │ ├── WaypointListFragment.scala │ │ │ │ ├── WaypointMenuItem.scala │ │ │ │ └── WaypointUtil.scala │ │ │ └── service │ │ │ │ ├── AndroServiceClient.scala │ │ │ │ ├── AndroidDirUpload.scala │ │ │ │ ├── AndroidSerial.scala │ │ │ │ ├── AndropilotService.scala │ │ │ │ ├── BluetoothConnection.scala │ │ │ │ ├── DroneShareClient.scala │ │ │ │ ├── FTDISerial.scala │ │ │ │ ├── FollowMe.scala │ │ │ │ ├── MavlinkAndroid.scala │ │ │ │ ├── NetworkStateReceiver.scala │ │ │ │ ├── PebbleClient.scala │ │ │ │ ├── PebbleVehicleListener.scala │ │ │ │ └── Speaker.scala │ │ │ ├── aserial │ │ │ └── AsyncSerial.scala │ │ │ ├── aspeech │ │ │ └── TTSClient.scala │ │ │ ├── gcsapi │ │ │ ├── AndroidWebserver.scala │ │ │ ├── CustomChromeClient.scala │ │ │ ├── MyWebView.scala │ │ │ └── WebActivity.scala │ │ │ ├── gmaps │ │ │ ├── Drawables.scala │ │ │ ├── Scene.scala │ │ │ └── SmartMarker.scala │ │ │ └── rest │ │ │ └── AndroidFileSystem.scala │ └── test │ │ └── scala │ │ └── .gitignore └── tests │ └── src │ └── main │ └── res │ └── values │ └── strings.xml ├── build.sbt ├── common ├── .gitignore ├── VehicleFSM.png ├── VehicleFSM.sm ├── VehicleFSM.svg ├── build.sbt ├── compile-statemachine.sh ├── disabled │ └── InstrumentedActor.scala ├── lib │ ├── org.mavlink.library.jar │ └── org.mavlink.util.jar └── src │ ├── main │ ├── protobuf │ │ └── webapi.proto │ ├── resources │ │ └── com │ │ │ └── geeksville │ │ │ └── flight │ │ │ └── apm.pdef.xml │ ├── scala │ │ ├── com │ │ │ ├── geeksville │ │ │ │ ├── akka │ │ │ │ │ ├── AkkaReflector.scala │ │ │ │ │ ├── AkkaTools.scala │ │ │ │ │ ├── Compatibility.scalla │ │ │ │ │ ├── DebuggableActor.scala │ │ │ │ │ ├── EventStream.scala │ │ │ │ │ ├── EventStreamDebugger.scala │ │ │ │ │ ├── InstrumentedActor.scala │ │ │ │ │ ├── MockAkka.scala │ │ │ │ │ ├── NamedActorSupervisor.scala │ │ │ │ │ ├── Scheduler.scala │ │ │ │ │ ├── Stopper.scala │ │ │ │ │ ├── TimesteppedActor.scala │ │ │ │ │ └── UncaughtExceptionActor.scala │ │ │ │ ├── apiproxy │ │ │ │ │ ├── APIConstants.scala │ │ │ │ │ ├── APIProxyActor.scala │ │ │ │ │ ├── GCSCallback.scala │ │ │ │ │ ├── GCSHooks.scala │ │ │ │ │ ├── GCSHooksImpl.scala │ │ │ │ │ ├── LiveUploader.scala │ │ │ │ │ └── TLogUploader.scala │ │ │ │ ├── dataflash │ │ │ │ │ └── DFReader.scala │ │ │ │ ├── flight │ │ │ │ │ ├── EventBusVehicleReceiver.scala │ │ │ │ │ ├── FenceModel.scala │ │ │ │ │ ├── FlightLead.scala │ │ │ │ │ ├── HeartbeatSender.scala │ │ │ │ │ ├── IGCPublisher.scala │ │ │ │ │ ├── IGCReader.scala │ │ │ │ │ ├── IGCWriter.scala │ │ │ │ │ ├── LiveOrPlaybackModel.scala │ │ │ │ │ ├── Location.scala │ │ │ │ │ ├── ParameterDocFile.scala │ │ │ │ │ ├── ParameterFile.scala │ │ │ │ │ ├── ParametersModel.scala │ │ │ │ │ ├── ParametersReadOnlyModel.scala │ │ │ │ │ ├── StressTestVehicle.scala │ │ │ │ │ ├── VehicleClient.scala │ │ │ │ │ ├── VehicleFSM.scala │ │ │ │ │ ├── VehicleListener.scala │ │ │ │ │ ├── VehicleModel.scala │ │ │ │ │ ├── VehicleSimulator.scala │ │ │ │ │ ├── Waypoint.scala │ │ │ │ │ ├── WaypointModel.scala │ │ │ │ │ └── WaypointsForMap.scala │ │ │ │ ├── gcsapi │ │ │ │ │ ├── ArrayAdapter.scala │ │ │ │ │ ├── GCSModel.scala │ │ │ │ │ ├── Gateway.scala │ │ │ │ │ ├── HierarchicalAdapter.scala │ │ │ │ │ ├── MapAdapter.scala │ │ │ │ │ ├── SmallAPI.scala │ │ │ │ │ ├── SmallAdapter.scala │ │ │ │ │ └── Webserver.scala │ │ │ │ ├── logback │ │ │ │ │ ├── Logger.scala │ │ │ │ │ ├── Logging.scala │ │ │ │ │ ├── MuteAllFilter.scala │ │ │ │ │ └── NameLevelFilter.scala │ │ │ │ ├── mavlink │ │ │ │ │ ├── BinaryMavlinkReader.scala │ │ │ │ │ ├── CanSendMavlink.scala │ │ │ │ │ ├── DataReducer.scala │ │ │ │ │ ├── HeartbeatMonitor.scala │ │ │ │ │ ├── LastSeenPackets.scala │ │ │ │ │ ├── LogBinaryMavlink.scala │ │ │ │ │ ├── LogIncomingMavlink.scala │ │ │ │ │ ├── MavlinkConstants.scala │ │ │ │ │ ├── MavlinkEventBus.scala │ │ │ │ │ ├── MavlinkNetGateway.scala │ │ │ │ │ ├── MavlinkReceiver.scala │ │ │ │ │ ├── MavlinkSender.scala │ │ │ │ │ ├── MavlinkStream.scala │ │ │ │ │ ├── MavlinkStreamReceiver.scala │ │ │ │ │ ├── MavlinkTCP.scala │ │ │ │ │ ├── MavlinkUDP.scala │ │ │ │ │ ├── MavlinkUtils.scala │ │ │ │ │ ├── TlogStreamReceiver.scala │ │ │ │ │ └── package.scala │ │ │ │ ├── mavserve │ │ │ │ │ └── MavServe.scala │ │ │ │ ├── sunspot │ │ │ │ │ └── SunspotClient.scala │ │ │ │ └── util │ │ │ │ │ ├── AnalyticsService.scala │ │ │ │ │ ├── Base32.scala │ │ │ │ │ ├── ByteOnlyInputStream.scala │ │ │ │ │ ├── Counted.scala │ │ │ │ │ ├── DateTools.scala │ │ │ │ │ ├── DebugContext.scala │ │ │ │ │ ├── DebugInputStream.scala │ │ │ │ │ ├── FileTools.scala │ │ │ │ │ ├── Gravatar.scala │ │ │ │ │ ├── HeadInputStream.scala │ │ │ │ │ ├── MathTools.scala │ │ │ │ │ ├── NetTools.scala │ │ │ │ │ ├── OSTools.scala │ │ │ │ │ ├── PartialFunctionTools.scala │ │ │ │ │ ├── QueueInputStream.scala │ │ │ │ │ ├── RingBuffer.scala │ │ │ │ │ ├── SimplePublisher.scala │ │ │ │ │ ├── TCPListener.scala │ │ │ │ │ ├── ThreadTools.scala │ │ │ │ │ ├── Throttled.scala │ │ │ │ │ ├── ThrottledActor.scala │ │ │ │ │ ├── UnbufferedSource.scala │ │ │ │ │ └── Using.scala │ │ │ └── ridemission │ │ │ │ └── rest │ │ │ │ ├── FileHandler.scala │ │ │ │ ├── HttpConstants.scala │ │ │ │ ├── JsonTools.scala │ │ │ │ ├── MicroRESTServer.scala │ │ │ │ ├── Request.scala │ │ │ │ └── Response.scala │ │ └── statemap │ │ │ └── statemap.scala │ └── webapp │ │ ├── .gitignore │ │ ├── README.haml │ │ ├── build-coffee.sh │ │ ├── build.sh │ │ ├── checklist │ │ ├── .gitignore │ │ ├── copter.haml │ │ └── plane.haml │ │ ├── coffee │ │ ├── checklist.coffee │ │ ├── gcsapi.coffee │ │ └── test-takeoff.coffee │ │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.min.css │ │ ├── custom.css │ │ └── jumbotron-narrow.css │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ │ ├── gcsapi-README.md │ │ ├── index.html │ │ ├── js │ │ ├── .gitignore │ │ ├── backbone.js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── checklist.js │ │ ├── jquery.js │ │ ├── json2.js │ │ ├── test-takeoff.js │ │ └── underscore.js │ │ ├── test-takeoff-aio.gcs.html │ │ └── test-takeoff.gcs.html │ └── test │ └── scala │ └── com │ └── geeksville │ └── dataflash │ └── DataflashTests.scala ├── generate-mavglue.sh ├── google-play-services ├── .gitignore ├── .project ├── build.sbt ├── lib │ ├── google-play-services.jar │ └── google-play-services.jar.properties └── src │ ├── .readme │ └── main │ ├── AndroidManifest.xml │ └── res │ ├── color │ ├── common_signin_btn_text_dark.xml │ └── common_signin_btn_text_light.xml │ ├── drawable-hdpi │ ├── common_signin_btn_icon_disabled_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_light.9.png │ ├── common_signin_btn_icon_disabled_light.9.png │ ├── common_signin_btn_icon_focus_dark.9.png │ ├── common_signin_btn_icon_focus_light.9.png │ ├── common_signin_btn_icon_normal_dark.9.png │ ├── common_signin_btn_icon_normal_light.9.png │ ├── common_signin_btn_icon_pressed_dark.9.png │ ├── common_signin_btn_icon_pressed_light.9.png │ ├── common_signin_btn_text_disabled_dark.9.png │ ├── common_signin_btn_text_disabled_focus_dark.9.png │ ├── common_signin_btn_text_disabled_focus_light.9.png │ ├── common_signin_btn_text_disabled_light.9.png │ ├── common_signin_btn_text_focus_dark.9.png │ ├── common_signin_btn_text_focus_light.9.png │ ├── common_signin_btn_text_normal_dark.9.png │ ├── common_signin_btn_text_normal_light.9.png │ ├── common_signin_btn_text_pressed_dark.9.png │ └── common_signin_btn_text_pressed_light.9.png │ ├── drawable-mdpi │ ├── common_signin_btn_icon_disabled_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_light.9.png │ ├── common_signin_btn_icon_disabled_light.9.png │ ├── common_signin_btn_icon_focus_dark.9.png │ ├── common_signin_btn_icon_focus_light.9.png │ ├── common_signin_btn_icon_normal_dark.9.png │ ├── common_signin_btn_icon_normal_light.9.png │ ├── common_signin_btn_icon_pressed_dark.9.png │ ├── common_signin_btn_icon_pressed_light.9.png │ ├── common_signin_btn_text_disabled_dark.9.png │ ├── common_signin_btn_text_disabled_focus_dark.9.png │ ├── common_signin_btn_text_disabled_focus_light.9.png │ ├── common_signin_btn_text_disabled_light.9.png │ ├── common_signin_btn_text_focus_dark.9.png │ ├── common_signin_btn_text_focus_light.9.png │ ├── common_signin_btn_text_normal_dark.9.png │ ├── common_signin_btn_text_normal_light.9.png │ ├── common_signin_btn_text_pressed_dark.9.png │ └── common_signin_btn_text_pressed_light.9.png │ ├── drawable-xhdpi │ ├── common_signin_btn_icon_disabled_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_dark.9.png │ ├── common_signin_btn_icon_disabled_focus_light.9.png │ ├── common_signin_btn_icon_disabled_light.9.png │ ├── common_signin_btn_icon_focus_dark.9.png │ ├── common_signin_btn_icon_focus_light.9.png │ ├── common_signin_btn_icon_normal_dark.9.png │ ├── common_signin_btn_icon_normal_light.9.png │ ├── common_signin_btn_icon_pressed_dark.9.png │ ├── common_signin_btn_icon_pressed_light.9.png │ ├── common_signin_btn_text_disabled_dark.9.png │ ├── common_signin_btn_text_disabled_focus_dark.9.png │ ├── common_signin_btn_text_disabled_focus_light.9.png │ ├── common_signin_btn_text_disabled_light.9.png │ ├── common_signin_btn_text_focus_dark.9.png │ ├── common_signin_btn_text_focus_light.9.png │ ├── common_signin_btn_text_normal_dark.9.png │ ├── common_signin_btn_text_normal_light.9.png │ ├── common_signin_btn_text_pressed_dark.9.png │ └── common_signin_btn_text_pressed_light.9.png │ ├── drawable │ ├── common_signin_btn_icon_dark.xml │ ├── common_signin_btn_icon_light.xml │ ├── common_signin_btn_text_dark.xml │ └── common_signin_btn_text_light.xml │ ├── values-af │ └── strings.xml │ ├── values-am │ └── strings.xml │ ├── values-ar │ └── strings.xml │ ├── values-be │ └── strings.xml │ ├── values-bg │ └── strings.xml │ ├── values-ca │ └── strings.xml │ ├── values-cs │ └── strings.xml │ ├── values-da │ └── strings.xml │ ├── values-de │ └── strings.xml │ ├── values-el │ └── strings.xml │ ├── values-en-rGB │ └── strings.xml │ ├── values-es-rUS │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-et │ └── strings.xml │ ├── values-fa │ └── strings.xml │ ├── values-fi │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-hi │ └── strings.xml │ ├── values-hr │ └── strings.xml │ ├── values-hu │ └── strings.xml │ ├── values-in │ └── strings.xml │ ├── values-it │ └── strings.xml │ ├── values-iw │ └── strings.xml │ ├── values-ja │ └── strings.xml │ ├── values-ko │ └── strings.xml │ ├── values-lt │ └── strings.xml │ ├── values-lv │ └── strings.xml │ ├── values-ms │ └── strings.xml │ ├── values-nb │ └── strings.xml │ ├── values-nl │ └── strings.xml │ ├── values-pl │ └── strings.xml │ ├── values-pt-rBR │ └── strings.xml │ ├── values-pt-rPT │ └── strings.xml │ ├── values-pt │ └── strings.xml │ ├── values-ro │ └── strings.xml │ ├── values-ru │ └── strings.xml │ ├── values-sk │ └── strings.xml │ ├── values-sl │ └── strings.xml │ ├── values-sr │ └── strings.xml │ ├── values-sv │ └── strings.xml │ ├── values-sw │ └── strings.xml │ ├── values-th │ └── strings.xml │ ├── values-tl │ └── strings.xml │ ├── values-tr │ └── strings.xml │ ├── values-uk │ └── strings.xml │ ├── values-vi │ └── strings.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values-zu │ └── strings.xml │ └── values │ ├── colors.xml │ ├── maps_attrs.xml │ └── strings.xml ├── httpcontent └── index.html ├── posixpilot ├── .gitignore ├── README.md ├── TODO.md ├── build.sbt ├── dumplog.sh ├── lib │ └── RXTXcomm.jar ├── libsrc │ ├── amd64 │ │ └── librxtxSerial.so │ ├── i686 │ │ └── librxtxSerial.so │ └── rxtx-2.2pre2.zip ├── run-jsbsim.sh ├── run-mavproxy-to-tablet.sh ├── run-mavproy.sh ├── run-sitl.sh └── src │ ├── main │ ├── java │ │ ├── .gitignore │ │ └── com │ │ │ └── geeksville │ │ │ └── shell │ │ │ └── ANSITerminal.java │ ├── logback.xml │ ├── resources │ │ ├── application.conf │ │ └── com │ │ │ └── geeksville │ │ │ └── flight │ │ │ └── lead │ │ │ ├── pretty-good-res-dumps-1hr.igc │ │ │ ├── steve-forslund-1hr-dumps-2009-03-20-CGP-xYYY-02.IGC │ │ │ ├── steve-miller-2hr-2012-07-03-Mussel-Rock.kml │ │ │ └── test.tlog │ └── scala │ │ ├── com │ │ └── geeksville │ │ │ ├── flight │ │ │ ├── lead │ │ │ │ ├── FlightLead.scala │ │ │ │ ├── NMEAParser.scala │ │ │ │ ├── PosixWebserver.scala │ │ │ │ ├── RCOverrideDebug.scala │ │ │ │ ├── ShellCommands.scala │ │ │ │ └── package.scala │ │ │ ├── package.scala │ │ │ ├── test │ │ │ │ └── package.scala │ │ │ └── wingman │ │ │ │ └── Wingman.scala │ │ │ ├── ftdi │ │ │ ├── FtdiDevice.scala │ │ │ ├── FtdiInputStream.scala │ │ │ ├── FtdiOutputStream.scala │ │ │ └── LibFtdi.scala │ │ │ ├── mavlink │ │ │ └── MavlinkFtdi.scala │ │ │ └── shell │ │ │ ├── ScalaConsole.scala │ │ │ ├── ScalaShell.scala │ │ │ └── SystemTools.scala │ │ └── net │ │ └── java │ │ └── dev │ │ └── sna │ │ ├── SNA.scala │ │ ├── SNAException.scala │ │ └── examples │ │ ├── Beep.scala │ │ ├── CreateFile.scala │ │ ├── EnumWindows.scala │ │ ├── GETSYSTEMTIME.scala │ │ ├── GetDiskFreeSpace.scala │ │ ├── GetDiskFreeSpace2.scala │ │ ├── GetLogicalDrives.scala │ │ ├── GetSystemTimeDemo.scala │ │ ├── GetSystemTimeDemo2.scala │ │ ├── Signal.scala │ │ ├── SignalTest.java │ │ └── Test01.scala │ └── test │ ├── java │ └── .gitignore │ └── scala │ └── .gitignore ├── project ├── Build.scala ├── build.properties └── plugins.sbt ├── test-call.json ├── test-call.sh └── thirdparty ├── README.md ├── org.mavlink.generator ├── .classpath ├── .pmd ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs ├── build.xml ├── org.mavlink.generator.doxyfile ├── readme.txt └── src │ └── org │ └── mavlink │ └── generator │ ├── FieldCompare.java │ ├── IMAVLinkTag.java │ ├── MAVLinkData.java │ ├── MAVLinkDataType.java │ ├── MAVLinkEntry.java │ ├── MAVLinkEnum.java │ ├── MAVLinkField.java │ ├── MAVLinkGenerator.java │ ├── MAVLinkHandler.java │ ├── MAVLinkMessage.java │ └── MAVLinkParam.java ├── org.mavlink.library ├── .classpath ├── .pmd ├── .project ├── .settings │ └── org.eclipse.jdt.core.prefs ├── build.xml ├── generated │ └── org │ │ └── mavlink │ │ ├── IMAVLinkCRC.java │ │ └── messages │ │ ├── FENCE_ACTION.java │ │ ├── FENCE_BREACH.java │ │ ├── IMAVLink.java │ │ ├── IMAVLinkMessageID.java │ │ ├── LIMITS_STATE.java │ │ ├── LIMIT_MODULE.java │ │ ├── MAVLINK_DATA_STREAM_TYPE.java │ │ ├── MAVLinkMessageCoder.java │ │ ├── MAVLinkMessageFactory.java │ │ ├── MAV_AUTOPILOT.java │ │ ├── MAV_CMD.java │ │ ├── MAV_CMD_ACK.java │ │ ├── MAV_COMPONENT.java │ │ ├── MAV_DATA_STREAM.java │ │ ├── MAV_FRAME.java │ │ ├── MAV_GOTO.java │ │ ├── MAV_MISSION_RESULT.java │ │ ├── MAV_MODE.java │ │ ├── MAV_MODE_FLAG.java │ │ ├── MAV_MODE_FLAG_DECODE_POSITION.java │ │ ├── MAV_MOUNT_MODE.java │ │ ├── MAV_PARAM_TYPE.java │ │ ├── MAV_RESULT.java │ │ ├── MAV_ROI.java │ │ ├── MAV_SEVERITY.java │ │ ├── MAV_STATE.java │ │ ├── MAV_SYS_STATUS_SENSOR.java │ │ ├── MAV_TYPE.java │ │ ├── RALLY_FLAGS.java │ │ └── ardupilotmega │ │ ├── msg_ahrs.java │ │ ├── msg_airspeed_autocal.java │ │ ├── msg_ap_adc.java │ │ ├── msg_attitude.java │ │ ├── msg_attitude_quaternion.java │ │ ├── msg_auth_key.java │ │ ├── msg_battery_status.java │ │ ├── msg_change_operator_control.java │ │ ├── msg_change_operator_control_ack.java │ │ ├── msg_command_ack.java │ │ ├── msg_command_long.java │ │ ├── msg_data16.java │ │ ├── msg_data32.java │ │ ├── msg_data64.java │ │ ├── msg_data96.java │ │ ├── msg_data_stream.java │ │ ├── msg_debug.java │ │ ├── msg_debug_vect.java │ │ ├── msg_digicam_configure.java │ │ ├── msg_digicam_control.java │ │ ├── msg_fence_fetch_point.java │ │ ├── msg_fence_point.java │ │ ├── msg_fence_status.java │ │ ├── msg_file_transfer_dir_list.java │ │ ├── msg_file_transfer_res.java │ │ ├── msg_file_transfer_start.java │ │ ├── msg_global_position_int.java │ │ ├── msg_global_position_setpoint_int.java │ │ ├── msg_global_vision_position_estimate.java │ │ ├── msg_gps_global_origin.java │ │ ├── msg_gps_raw_int.java │ │ ├── msg_gps_status.java │ │ ├── msg_heartbeat.java │ │ ├── msg_highres_imu.java │ │ ├── msg_hil_controls.java │ │ ├── msg_hil_gps.java │ │ ├── msg_hil_optical_flow.java │ │ ├── msg_hil_rc_inputs_raw.java │ │ ├── msg_hil_sensor.java │ │ ├── msg_hil_state.java │ │ ├── msg_hil_state_quaternion.java │ │ ├── msg_hwstatus.java │ │ ├── msg_limits_status.java │ │ ├── msg_local_position_ned.java │ │ ├── msg_local_position_ned_system_global_offset.java │ │ ├── msg_local_position_setpoint.java │ │ ├── msg_manual_control.java │ │ ├── msg_manual_setpoint.java │ │ ├── msg_meminfo.java │ │ ├── msg_memory_vect.java │ │ ├── msg_mission_ack.java │ │ ├── msg_mission_clear_all.java │ │ ├── msg_mission_count.java │ │ ├── msg_mission_current.java │ │ ├── msg_mission_item.java │ │ ├── msg_mission_item_reached.java │ │ ├── msg_mission_request.java │ │ ├── msg_mission_request_list.java │ │ ├── msg_mission_request_partial_list.java │ │ ├── msg_mission_set_current.java │ │ ├── msg_mission_write_partial_list.java │ │ ├── msg_mount_configure.java │ │ ├── msg_mount_control.java │ │ ├── msg_mount_status.java │ │ ├── msg_named_value_float.java │ │ ├── msg_named_value_int.java │ │ ├── msg_nav_controller_output.java │ │ ├── msg_omnidirectional_flow.java │ │ ├── msg_optical_flow.java │ │ ├── msg_param_request_list.java │ │ ├── msg_param_request_read.java │ │ ├── msg_param_set.java │ │ ├── msg_param_value.java │ │ ├── msg_ping.java │ │ ├── msg_radio.java │ │ ├── msg_radio_status.java │ │ ├── msg_rally_fetch_point.java │ │ ├── msg_rally_point.java │ │ ├── msg_rangefinder.java │ │ ├── msg_raw_imu.java │ │ ├── msg_raw_pressure.java │ │ ├── msg_rc_channels_override.java │ │ ├── msg_rc_channels_raw.java │ │ ├── msg_rc_channels_scaled.java │ │ ├── msg_request_data_stream.java │ │ ├── msg_roll_pitch_yaw_rates_thrust_setpoint.java │ │ ├── msg_roll_pitch_yaw_speed_thrust_setpoint.java │ │ ├── msg_roll_pitch_yaw_thrust_setpoint.java │ │ ├── msg_safety_allowed_area.java │ │ ├── msg_safety_set_allowed_area.java │ │ ├── msg_scaled_imu.java │ │ ├── msg_scaled_pressure.java │ │ ├── msg_sensor_offsets.java │ │ ├── msg_servo_output_raw.java │ │ ├── msg_set_global_position_setpoint_int.java │ │ ├── msg_set_gps_global_origin.java │ │ ├── msg_set_local_position_setpoint.java │ │ ├── msg_set_mag_offsets.java │ │ ├── msg_set_mode.java │ │ ├── msg_set_quad_motors_setpoint.java │ │ ├── msg_set_quad_swarm_led_roll_pitch_yaw_thrust.java │ │ ├── msg_set_quad_swarm_roll_pitch_yaw_thrust.java │ │ ├── msg_set_roll_pitch_yaw_speed_thrust.java │ │ ├── msg_set_roll_pitch_yaw_thrust.java │ │ ├── msg_setpoint_6dof.java │ │ ├── msg_setpoint_8dof.java │ │ ├── msg_sim_state.java │ │ ├── msg_simstate.java │ │ ├── msg_state_correction.java │ │ ├── msg_statustext.java │ │ ├── msg_sys_status.java │ │ ├── msg_system_time.java │ │ ├── msg_vfr_hud.java │ │ ├── msg_vicon_position_estimate.java │ │ ├── msg_vision_position_estimate.java │ │ ├── msg_vision_speed_estimate.java │ │ └── msg_wind.java ├── org.mavlink.library.jardesc ├── readme.txt ├── src │ └── org │ │ └── mavlink │ │ ├── MAVLinkReader.java │ │ ├── io │ │ ├── LittleEndianDataInputStream.java │ │ └── LittleEndianDataOutputStream.java │ │ └── messages │ │ └── MAVLinkMessage.java └── test │ └── org │ └── mavlink │ ├── ExtractionLog.java │ └── TestMavlinkReader.java └── org.mavlink.util ├── .classpath ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── build.xml ├── org.mavlink.util.jardesc └── src └── org └── mavlink ├── IMAVLinkMessage.java └── MAVLinkCRC.java /.gitignore: -------------------------------------------------------------------------------- 1 | .settings 2 | *.class 3 | .cache 4 | *~ 5 | target 6 | .history 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "scandroid"] 2 | path = scandroid 3 | url = git://github.com/geeksville/scandroid.git 4 | [submodule "droneapi-protobuf"] 5 | path = droneapi-protobuf 6 | url = git@github.com:diydrones/droneapi-protobuf.git 7 | -------------------------------------------------------------------------------- /.sbtopts: -------------------------------------------------------------------------------- 1 | -java-home /usr/lib/jvm/java-6-openjdk-amd64 2 | -------------------------------------------------------------------------------- /.sbtrc: -------------------------------------------------------------------------------- 1 | alias boot = ;reload ;project andropilot ;iflast shell 2 | -------------------------------------------------------------------------------- /andropilot/.gitignore: -------------------------------------------------------------------------------- 1 | geeksville-release-key.keystore 2 | .settings 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /andropilot/README.md: -------------------------------------------------------------------------------- 1 | # Andropilot - a Mavlink/Arduplane ground controller for Android 2 | 3 | A prebuilt version of the Android application is [on the Play store](https://play.google.com/store/apps/details?id=com.geeksville.andropilot). If you are not interested in coding, you probably want to go there. 4 | 5 | Copyright 2012 Kevin Hester, GPLv3 license. 6 | 7 | To build this application, see README.md in the root of this repository. 8 | -------------------------------------------------------------------------------- /andropilot/adb-connect.sh: -------------------------------------------------------------------------------- 1 | while true; do adb connect 192.168.0.39; sleep 15; done & 2 | -------------------------------------------------------------------------------- /andropilot/adbconnect.sh: -------------------------------------------------------------------------------- 1 | adb connect 192.168.1.176:5555 2 | -------------------------------------------------------------------------------- /andropilot/art/Icons/Forever_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Forever_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Forever_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Forever_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa1__blue_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa1__blue_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa2__blue_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa2__blue_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa2__red_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa2__red_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa2__red_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa2__red_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa2__yellow_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa2__yellow_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Hexa2__yellow_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Hexa2__yellow_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Land_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Land_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Land_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Land_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Number_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Number_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Number_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Number_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_blue_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_blue_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_blue_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_blue_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_red_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_red_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_red_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_red_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_yellow_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_yellow_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad1_yellow_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad1_yellow_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_blue_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_blue_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_blue_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_blue_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_red_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_red_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_red_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_red_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_yellow_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_yellow_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Quad2_yellow_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Quad2_yellow_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/RTL_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/RTL_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/RTL_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/RTL_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/TakeOff_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/TakeOff_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/TakeOff_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/TakeOff_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Timed_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Timed_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/Timed_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/Timed_48.png -------------------------------------------------------------------------------- /andropilot/art/Icons/waypoint_dot_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/waypoint_dot_32.png -------------------------------------------------------------------------------- /andropilot/art/Icons/waypoint_dot_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/Icons/waypoint_dot_48.png -------------------------------------------------------------------------------- /andropilot/art/airplane-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/airplane-48x48.png -------------------------------------------------------------------------------- /andropilot/art/altimeter-icon-28x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/altimeter-icon-28x48.png -------------------------------------------------------------------------------- /andropilot/art/altimeter-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/altimeter-icon.png -------------------------------------------------------------------------------- /andropilot/art/checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/checklist.png -------------------------------------------------------------------------------- /andropilot/art/droneshare-taskbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/droneshare-taskbar.png -------------------------------------------------------------------------------- /andropilot/art/feature-graphic-1024x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/feature-graphic-1024x500.png -------------------------------------------------------------------------------- /andropilot/art/joysticks-10inch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/joysticks-10inch.png -------------------------------------------------------------------------------- /andropilot/art/new-ui-wip-no-sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/new-ui-wip-no-sidebar.png -------------------------------------------------------------------------------- /andropilot/art/new-ui-wip-sidebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/new-ui-wip-sidebar.png -------------------------------------------------------------------------------- /andropilot/art/new-ui-wip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/new-ui-wip.png -------------------------------------------------------------------------------- /andropilot/art/paper-airplane-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/paper-airplane-128x128.png -------------------------------------------------------------------------------- /andropilot/art/paper-airplane-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/paper-airplane-16x16.png -------------------------------------------------------------------------------- /andropilot/art/paper-airplane-180x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/paper-airplane-180x120.png -------------------------------------------------------------------------------- /andropilot/art/paper-airplane-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/paper-airplane-512x512.png -------------------------------------------------------------------------------- /andropilot/art/paper-airplane-75x75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/paper-airplane-75x75.png -------------------------------------------------------------------------------- /andropilot/art/read-only-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/read-only-mode.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-1.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-10inch-copterfence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-10inch-copterfence.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-10inch-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-10inch-portrait.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-2.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-3.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-4.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-fence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-fence.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-hud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-hud.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-landscape.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-overview.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-parameters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-parameters.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-phone-joystick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-phone-joystick.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-phone-wp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-phone-wp.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-portrait.png -------------------------------------------------------------------------------- /andropilot/art/screenshot-waypoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/art/screenshot-waypoint.png -------------------------------------------------------------------------------- /andropilot/build.sbt: -------------------------------------------------------------------------------- 1 | import sbtandroid.AndroidKeys._ 2 | 3 | name := "andropilot" 4 | 5 | version := "2.1.11" 6 | 7 | versionCode := 20111 8 | 9 | net.virtualvoid.sbt.graph.Plugin.graphSettings 10 | 11 | // Github.settings 12 | 13 | libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.2.3" 14 | 15 | libraryDependencies += "google-play-services" % "google-play-services_2.10" % "0.1-SNAPSHOT" artifacts(Artifact("google-play-services_2.10", "apklib", "apklib")) 16 | 17 | scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation", "-optimise") // , "-feature" 18 | 19 | javacOptions ++= Seq("-source", "1.6", "-target", "1.6") // Needed for android 20 | 21 | platformName in Android := "android-19" // USB host mode appeared in 3.1 (12), Ice cream sandwich and later is 80% market share, so I could drop to 15, kitkat 4.4 is 19 22 | 23 | dxMemory in Android := "-JXmx1024m" 24 | 25 | keyalias in Android := "geeksville-android-key" 26 | 27 | keystorePath in Android := file("andropilot/geeksville-release-key.keystore") 28 | 29 | //signRelease in Android <<= signReleaseTask 30 | 31 | //signRelease in Android <<= (signRelease in Android) dependsOn (packageRelease in Android) 32 | 33 | //githubRepo in Android := "geeksville/arduleader" 34 | -------------------------------------------------------------------------------- /andropilot/config/application.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Our akka config file 3 | # See http://doc.akka.io/docs/akka/snapshot/general/configuration.html 4 | # 5 | 6 | akka { 7 | # Set to on to debug these settings 8 | log-config-on-start = off 9 | 10 | # Log level used by the configured loggers (see "event-handlers") as soon 11 | # as they have been started; before that, see "stdout-loglevel" 12 | # Options: ERROR, WARNING, INFO, DEBUG 13 | loglevel = DEBUG 14 | 15 | # Log level for the very basic logger activated during AkkaApplication startup 16 | # Options: ERROR, WARNING, INFO, DEBUG 17 | stdout-loglevel = DEBUG 18 | 19 | event-handlers = ["com.geeksville.andropilot.AndroidAkkaLogger"] 20 | 21 | actor { 22 | default-dispatcher { 23 | # Use bounded mailboxes 24 | mailbox-capacity = 50 25 | mailbox-push-timeout-time = 5000ms 26 | } 27 | 28 | debug { 29 | receive = on 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /andropilot/display-debug-cert.sh: -------------------------------------------------------------------------------- 1 | echo displaying the debug build cert 2 | keytool -list -v -keystore $ANDROID_SDK_HOME/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android 3 | -------------------------------------------------------------------------------- /andropilot/display-release-cert.sh: -------------------------------------------------------------------------------- 1 | keytool -list -v -keystore geeksville-release-key.keystore -alias geeksville-android-key 2 | -------------------------------------------------------------------------------- /andropilot/lib/FlurryAgent.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/FlurryAgent.jar -------------------------------------------------------------------------------- /andropilot/lib/aws-android-sdk-1.4.6-core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/aws-android-sdk-1.4.6-core.jar -------------------------------------------------------------------------------- /andropilot/lib/aws-android-sdk-1.4.6-s3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/aws-android-sdk-1.4.6-s3.jar -------------------------------------------------------------------------------- /andropilot/lib/bugsense-3.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/bugsense-3.5.jar -------------------------------------------------------------------------------- /andropilot/lib/d2xx.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/d2xx.jar -------------------------------------------------------------------------------- /andropilot/lib/google-play-services.jar: -------------------------------------------------------------------------------- 1 | ../../google-play-services/lib/google-play-services.jar -------------------------------------------------------------------------------- /andropilot/lib/logback-android-1.0.7-1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/logback-android-1.0.7-1.jar -------------------------------------------------------------------------------- /andropilot/lib/pebble-kit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/pebble-kit.jar -------------------------------------------------------------------------------- /andropilot/lib/usb-serial-for-android-snapshot.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/lib/usb-serial-for-android-snapshot.jar -------------------------------------------------------------------------------- /andropilot/logcat.sh: -------------------------------------------------------------------------------- 1 | adb shell setprop log.redirect-stdio true 2 | adb logcat *:D | grep -v UsbRequest 3 | -------------------------------------------------------------------------------- /andropilot/src/main/assets/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | %logger{0} 7 | 8 | 9 | 10 | %-5level %-36logger{36}: %msg%n 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /andropilot/src/main/assets/webapp: -------------------------------------------------------------------------------- 1 | ../../../../common/src/main/webapp -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/quad_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/quad_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/quad_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/quad_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/quad_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/quad_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_dot.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_forever.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_forever.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_land.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_land.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_number.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_number.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_rtl.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_takeoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_takeoff.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-hdpi/waypoint_timed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-hdpi/waypoint_timed.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/arrow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/blue_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/blue_dot.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/flag.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/hospitals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/hospitals.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/in_flight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/in_flight.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/lz_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/lz_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/lz_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/lz_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/lz_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/lz_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/plane_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/plane_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/plane_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/plane_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/plane_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/plane_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/quad_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/quad_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/quad_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/quad_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/quad_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/quad_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/rangerstation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/rangerstation.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_dot.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_forever.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_forever.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_land.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_land.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_number.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_number.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_rtl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_rtl.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_takeoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_takeoff.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/waypoint_timed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/waypoint_timed.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-mdpi/yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-mdpi/yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable-nodpi/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable-nodpi/watch.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/arrow.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/arrow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/blue.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/blue_dot.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/blue_dot.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/flag.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/flag.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/hospitals.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/hospitals.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/icon.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/icon.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/in_flight.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/in_flight.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/lz_blue.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/lz_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/lz_red.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/lz_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/lz_yellow.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/lz_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/my_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/my_border_transparent.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 8 | -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/plane_blue.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/plane_blue.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/plane_red.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/plane_red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/plane_yellow.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/plane_yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/rangerstation.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/rangerstation.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/red.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/red.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/rounded_textbackground.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/square_textbackground.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_down_disabled.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_down_disabled.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_down_disabled_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_down_disabled_focused.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_down_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_down_normal.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_down_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_down_pressed.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_down_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_down_selected.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_input_disabled.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_input_disabled.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_input_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_input_normal.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_input_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_input_pressed.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_input_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_input_selected.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_up_disabled.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_up_disabled.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_up_disabled_focused.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_up_disabled_focused.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_up_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_up_normal.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_up_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_up_pressed.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/timepicker_up_selected.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/main/res/drawable/timepicker_up_selected.9.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/waypoint.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/waypoint.png -------------------------------------------------------------------------------- /andropilot/src/main/res/drawable/yellow.png: -------------------------------------------------------------------------------- 1 | ../drawable-mdpi/yellow.png -------------------------------------------------------------------------------- /andropilot/src/main/res/layout-w480dp/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 23 | 24 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/device_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/hud_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/min_max_current_slider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/pager_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 22 | 23 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/parameter_pane.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 19 | 20 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/parameter_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/progress_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/rcchannel_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 20 | 21 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/simple_list_item_1_small.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/splash_fragment.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/statusmsg_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /andropilot/src/main/res/layout/web_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /andropilot/src/main/res/menu/waypoint_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 13 | 18 | 19 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16 | 17 | Disabled 18 | Uplink (send UDP to another host) 19 | Downlink (receive UDP from another host) 20 | TCP to another host 21 | 22 | 23 | Disabled 24 | Uplink 25 | Downlink 26 | TCPUplink 27 | 28 | 29 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #F9E60E 4 | #F9F89D 5 | #F7BE45 6 | #F7D896 7 | #19FCDA 8 | #D9F7F2 9 | #ACA899 10 | #FFFFFF 11 | #DDDDDD 12 | 13 | #000000 14 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values/strings-spoken.xml: -------------------------------------------------------------------------------- 1 | 2 | en 3 | 4 | %s meters 5 | %s percent 6 | Warn Volt 7 | Warn Battery 8 | Warn Radio 9 | Warn GPS 10 | Heartbeat lost 11 | Joystick off 12 | Joystick on 13 | 14 | 33 | 34 | -------------------------------------------------------------------------------- /andropilot/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | 29 | 30 | -------------------------------------------------------------------------------- /andropilot/src/main/res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /andropilot/src/main/res/xml/preferences_serial.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/AndroidAkkaLogger.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot 2 | 3 | import akka.actor.Actor 4 | import akka.event.Logging._ 5 | import android.util.Log 6 | 7 | class AndroidAkkaLogger extends Actor { 8 | def receive = { 9 | case Error(cause, logSource, logClass, message) ⇒ 10 | Log.e("com.geeksville.akka", s"$message [$logSource]: $cause") 11 | 12 | case Warning(logSource, logClass, message) ⇒ 13 | Log.w("com.geeksville.akka", s"$message [$logSource]") 14 | 15 | case Info(logSource, logClass, message) ⇒ 16 | Log.i("com.geeksville.akka", s"$message [$logSource]") 17 | 18 | case Debug(logSource, logClass, message) ⇒ 19 | Log.d("com.geeksville.akka", s"$message [$logSource]") 20 | 21 | case InitializeLogger(_) ⇒ 22 | Log.d("com.geeksville.akka", "Logging started") 23 | sender ! LoggerInitialized 24 | } 25 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/MyBackupAgent.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot 2 | 3 | import android.app.backup.BackupAgentHelper 4 | import android.app.backup.SharedPreferencesBackupHelper 5 | 6 | class MyBackupAgent extends BackupAgentHelper { 7 | 8 | // A key to uniquely identify the set of backup data 9 | val PREFS_BACKUP_KEY = "default" 10 | 11 | // Allocate a helper and add it to the backup agent 12 | override def onCreate() { 13 | // The name of the SharedPreferences file 14 | val PREFS = getPackageName() + "_preferences" 15 | 16 | val helper = new SharedPreferencesBackupHelper(this, PREFS) 17 | addHelper(PREFS_BACKUP_KEY, helper) 18 | } 19 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/UsesDirectories.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot 2 | import android.os.Environment 3 | import java.io.File 4 | import com.ridemission.scandroid.UsesResources 5 | 6 | trait UsesDirectories extends UsesResources { 7 | /** 8 | * Where we should spool our output files (if allowed) 9 | */ 10 | def sdDirectory = { 11 | if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) 12 | None 13 | else { 14 | val sdcard = Environment.getExternalStorageDirectory() 15 | if (!sdcard.exists()) 16 | None 17 | else 18 | Some(new File(sdcard, S(R.string.app_name).toLowerCase)) 19 | } 20 | } 21 | 22 | def logDirectory = sdDirectory.map { sd => 23 | val f = new File(sd, "newlogs") 24 | f.mkdirs() 25 | f 26 | } 27 | def checklistDirectory = sdDirectory.map { sd => 28 | val f = new File(sd, "checklists") 29 | f.mkdirs() 30 | f 31 | } 32 | def uploadedDirectory = sdDirectory.map { sd => 33 | val f = new File(sd, "uploaded") 34 | f.mkdirs() 35 | f 36 | } 37 | def paramDirectory = sdDirectory.map { sd => 38 | val f = new File(sd, "param-files") 39 | f.mkdirs() 40 | f 41 | } 42 | def waypointDirectory = sdDirectory.map { sd => 43 | val f = new File(sd, "waypoints") 44 | f.mkdirs() 45 | f 46 | } 47 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/NotificationIds.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | object NotificationIds { 4 | val vehicleConnectedId = 1 5 | val setupDroneshareId = 2 6 | val uploadId = 10 // All upload ids are higher than this 7 | 8 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/ParameterPane.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import com.geeksville.andropilot.R 4 | import android.view.View 5 | import com.ridemission.scandroid.AndroidLogger 6 | 7 | class ParameterPane extends LayoutFragment(R.layout.parameter_pane) with AndroidLogger { 8 | override def onViewCreated(v: View) { 9 | super.onViewCreated(v) 10 | 11 | debug("Creating child fragments") 12 | 13 | recreateFragment(R.id.parameter_list_fragment, "paramlist", new ParameterListFragment) 14 | recreateFragment(R.id.parameter_info_fragment, "paraminfo", new ParameterInfoFragment) 15 | } 16 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/ProgressList.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import android.support.v4.app.ListFragment 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import android.os.Bundle 7 | import com.geeksville.andropilot.R 8 | import android.widget.ProgressBar 9 | 10 | /** 11 | * A mixin that adds a progress bar while loading 12 | */ 13 | trait ProgressList extends ListFragment { 14 | protected def progressBar = Option(getView).map(_.findViewById(android.R.id.empty).asInstanceOf[ProgressBar]) 15 | 16 | override def onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle) = { 17 | val view = inflater.inflate(R.layout.progress_list, container, false); 18 | view 19 | } 20 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/RadioTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import org.mavlink.messages.ardupilotmega.msg_radio 4 | import com.ridemission.scandroid.AndroidLogger 5 | 6 | object RadioTools extends AndroidLogger { 7 | 8 | /** 9 | * Given a current distance in meters and a fadeMargin, estimate the distance where we will lose comms 10 | */ 11 | def estimateRange(fadeMargin: Float, curDist: Float) = { 12 | // Per Tridge 13 | val range = curDist * math.pow(2.0, fadeMargin / 6) 14 | debug(s"margin $fadeMargin, curDist $curDist => range=$range") 15 | range 16 | } 17 | 18 | def estimateRangePair(n: msg_radio, curDist: Float) = { 19 | val fadeMargin = 5 // Per Michael O 20 | val localFadeDb = math.max((n.rssi - n.noise) / 2.0f - fadeMargin, 0.0f) 21 | val remFadeDb = math.max((n.remrssi - n.remnoise) / 2.0f - fadeMargin, 0.0f) 22 | 23 | estimateRange(localFadeDb, curDist).toInt -> estimateRange(remFadeDb, curDist).toInt 24 | } 25 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/RcChannelsFragment.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import scala.collection.JavaConverters._ 6 | import android.widget.SimpleAdapter 7 | import org.mavlink.messages.ardupilotmega.msg_rc_channels_raw 8 | import com.geeksville.flight.MsgRcChannelsChanged 9 | import com.geeksville.util.ThreadTools._ 10 | import android.support.v4.app.ListFragment 11 | import com.geeksville.andropilot.R 12 | import com.geeksville.andropilot.service._ 13 | import com.ridemission.scandroid._ 14 | import com.geeksville.akka.InstrumentedActor 15 | 16 | class RcChannelsFragment extends SimpleListFragment with UsesResources { 17 | 18 | override def onVehicleReceive: InstrumentedActor.Receiver = { 19 | case MsgRcChannelsChanged => 20 | if (isVisible) { 21 | //debug("Received Rc channels") 22 | handler.post(updateList _) 23 | } 24 | } 25 | 26 | private def rcToSeq(m: Seq[Int]) = 27 | m.zipWithIndex.map { 28 | case (a, i) => 29 | S(R.string.channel).format(i + 1) -> a 30 | } 31 | 32 | protected def makeAdapter(): Option[SimpleAdapter] = { 33 | for { v <- myVehicle } yield { 34 | seqToAdapter(rcToSeq(v.rcChannels)) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/SplashFragment.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import android.support.v4.app.DialogFragment 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import android.os.Bundle 7 | import com.geeksville.andropilot.R 8 | 9 | class SplashFragment extends DialogFragment { 10 | 11 | override def onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle) = { 12 | val view = inflater.inflate(R.layout.splash_fragment, container) 13 | getDialog().setTitle(R.string.app_name) 14 | 15 | view 16 | } 17 | 18 | // this.dismiss(); 19 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/WaypointMenuItem.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | /** 4 | * A standard interface for any waypoint like object that can be edited 5 | */ 6 | trait WaypointMenuItem { 7 | /** 8 | * Can the user see/change auto continue 9 | */ 10 | def isAllowAutocontinue = false 11 | def isAutocontinue = false 12 | def isAutocontinue_=(b: Boolean) { throw new Exception("Not implemented") } 13 | 14 | def isAltitudeEditable = false 15 | def altitude = 0.0 16 | def altitude_=(n: Double) { throw new Exception("Not implemented") } 17 | 18 | def numParams = 0 19 | def getParam(i: Int) = 0.0f 20 | def setParam(i: Int, n: Float) { throw new Exception("Not implemented") } 21 | 22 | def isAllowGoto = false 23 | def isAllowAdd = false 24 | def isAllowChangeType = false 25 | def isAllowDelete = false 26 | 27 | /// Waypoint type 28 | def typStr = "unknown" 29 | def typStr_=(s: String) { throw new Exception("Not implemented") } 30 | 31 | def isAllowContextMenu = true 32 | 33 | /** 34 | * Have vehicle go to this waypoint 35 | */ 36 | def doGoto() { throw new Exception("Not yet implemented") } 37 | def doAdd() { throw new Exception("Not yet implemented") } 38 | def doDelete() { throw new Exception("Not yet implemented") } 39 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/andropilot/gui/WaypointUtil.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.andropilot.gui 2 | 3 | import org.mavlink.messages.MAV_CMD 4 | import com.geeksville.andropilot.R 5 | 6 | /** 7 | * Android specific waypoint utilities. 8 | */ 9 | object WaypointUtil { 10 | val wpToDrawable = Map(MAV_CMD.MAV_CMD_NAV_TAKEOFF -> R.drawable.waypoint_takeoff, 11 | MAV_CMD.MAV_CMD_NAV_WAYPOINT -> R.drawable.waypoint_dot, 12 | MAV_CMD.MAV_CMD_NAV_LAND -> R.drawable.waypoint_land, 13 | MAV_CMD.MAV_CMD_NAV_LOITER_UNLIM -> R.drawable.waypoint_forever, 14 | MAV_CMD.MAV_CMD_NAV_LOITER_TURNS -> R.drawable.waypoint_number, 15 | MAV_CMD.MAV_CMD_NAV_LOITER_TIME -> R.drawable.waypoint_timed, 16 | MAV_CMD.MAV_CMD_NAV_RETURN_TO_LAUNCH -> R.drawable.waypoint_rtl, 17 | MAV_CMD.MAV_CMD_NAV_LAND -> R.drawable.waypoint_land, 18 | MAV_CMD.MAV_CMD_DO_JUMP -> R.drawable.yellow) 19 | 20 | val defaultDrawable = R.drawable.blue 21 | 22 | /// Get a drawable suitable for use by android 23 | def toDrawable(cmd: Int) = wpToDrawable.getOrElse(cmd, defaultDrawable) 24 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/gcsapi/AndroidWebserver.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import com.geeksville.gcsapi._ 4 | import com.ridemission.rest.FileHandler 5 | import android.content.Context 6 | import com.geeksville.rest.AndroidFilesystem 7 | import com.geeksville.andropilot.UsesDirectories 8 | import com.ridemission.rest.JavaFileSystem 9 | 10 | /** 11 | * A GCSApi webserver that knows to pull static content from the local filesystem 12 | */ 13 | class AndroidWebserver(val acontext: Context, root: SmallAPI, localonly: Boolean = true) extends Webserver(root, localonly) with UsesDirectories { 14 | // FIXME - we currently assume the cwd is the default of 'posixpilot' 15 | server.addHandler(new FileHandler("/static", new AndroidFilesystem(acontext.getAssets, "webapp/"))) 16 | 17 | // Allow users to place custom checklists in /sdcard/andropilot/checklist/plane.html or copter.html. 18 | checklistDirectory.foreach { dir => 19 | server.addHandler(new FileHandler("/static/checklist", new JavaFileSystem(dir))) 20 | } 21 | } -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/gcsapi/CustomChromeClient.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import android.app._ 4 | import android.webkit._ 5 | import android.os.Bundle 6 | import android.widget._ 7 | import android.view._ 8 | import android.content._ 9 | import android.os._ 10 | import android.text.util._ 11 | import com.ridemission.scandroid.AndroidLogger 12 | 13 | /// Bridges javascript debug messages into the Android log 14 | class CustomChromeClient extends WebChromeClient with AndroidLogger { 15 | override def onJsAlert(view: WebView, url: String, message: String, result: JsResult) = { 16 | warn(message) // FIXME - toast instead? 17 | result.confirm() 18 | true 19 | } 20 | 21 | override def onConsoleMessage(m: ConsoleMessage) = { 22 | val formatted = "%s %s (%s:%d)".format(m.messageLevel, m.message, m.sourceId, m.lineNumber) 23 | m.messageLevel match { 24 | case ConsoleMessage.MessageLevel.ERROR => error(formatted) 25 | case ConsoleMessage.MessageLevel.LOG => info(formatted) 26 | case ConsoleMessage.MessageLevel.WARNING => warn(formatted) 27 | case _ => debug(formatted) 28 | } 29 | 30 | true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /andropilot/src/main/scala/com/geeksville/gcsapi/MyWebView.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import android.webkit._ 4 | import android.util._ 5 | import android.content._ 6 | 7 | // work around for android bug http://stackoverflow.com/questions/7156420/how-can-i-destroy-the-webview-activity-and-the-video-in-webview 8 | class MyWebView(context: Context, attrs: AttributeSet) extends WebView(context.getApplicationContext(), attrs) { 9 | } -------------------------------------------------------------------------------- /andropilot/src/test/scala/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/andropilot/src/test/scala/.gitignore -------------------------------------------------------------------------------- /andropilot/tests/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | My Android Project 3 | -------------------------------------------------------------------------------- /build.sbt: -------------------------------------------------------------------------------- 1 | name := "scalafly" 2 | 3 | version := "0.1" 4 | 5 | scalaVersion in ThisBuild := "2.10.4" // To match version used by scala-ide 6 | 7 | resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" 8 | 9 | net.virtualvoid.sbt.graph.Plugin.graphSettings 10 | 11 | libraryDependencies += "org.scala-lang" % "scala-compiler" % "2.10.4" withSources() 12 | 13 | libraryDependencies += "org.scala-lang" % "jline" % "2.10.4" withSources() 14 | 15 | scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation", "-optimise") // , "-feature" 16 | 17 | javacOptions ++= Seq("-source", "1.6", "-target", "1.6") // Needed for android 18 | 19 | EclipseKeys.createSrc in ThisBuild := EclipseCreateSrc.Default + EclipseCreateSrc.Resource // Include resources dir in eclipse classpath 20 | 21 | EclipseKeys.withSource in ThisBuild := true // Try to include source for libs 22 | 23 | EclipseKeys.relativizeLibs in ThisBuild := false // Doesn't seem to work for lib directory 24 | -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /.classpath 2 | /.project 3 | 4 | -------------------------------------------------------------------------------- /common/VehicleFSM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/VehicleFSM.png -------------------------------------------------------------------------------- /common/build.sbt: -------------------------------------------------------------------------------- 1 | // name := "common" 2 | 3 | version := "0.1" 4 | 5 | resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" 6 | 7 | scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation", "-optimise") // , "-feature" 8 | 9 | libraryDependencies += "com.typesafe.akka" %% "akka-actor" % "2.4-SNAPSHOT" 10 | 11 | libraryDependencies += "com.typesafe.akka" %% "akka-slf4j" % "2.4-SNAPSHOT" 12 | 13 | unmanagedResourceDirectories in Compile <+= baseDirectory( _ / "src" / "main" / "scala" ) 14 | 15 | unmanagedResourceDirectories in Compile <+= baseDirectory( _ / "src" / "main" / "java" ) 16 | 17 | libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.0.9" withSources() 18 | 19 | libraryDependencies += "net.sandrogrzicic" %% "scalabuff-runtime" % "1.3.7" withSources() 20 | 21 | libraryDependencies += "com.google.protobuf" % "protobuf-java" % "2.5.0" withSources() 22 | 23 | libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.0" % "test" 24 | -------------------------------------------------------------------------------- /common/compile-statemachine.sh: -------------------------------------------------------------------------------- 1 | JAVABIN=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 2 | SMCJAR=~/packages/state-machine-compiler/bin/Smc.jar 3 | 4 | $JAVABIN -jar $SMCJAR -scala -d src/main/scala/com/geeksville/flight VehicleFSM.sm 5 | $JAVABIN -jar $SMCJAR -graph -glevel 0 VehicleFSM.sm 6 | 7 | dot -Tsvg VehicleFSM.dot >VehicleFSM.svg 8 | dot -Tpng VehicleFSM.dot >VehicleFSM.png 9 | rm VehicleFSM.dot 10 | 11 | gnome-open VehicleFSM.svg 12 | -------------------------------------------------------------------------------- /common/disabled/InstrumentedActor.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.Actor 4 | import akka.actor.ActorLogging 5 | 6 | /** 7 | * Mixin to add a number of debugging utilities to actors 8 | */ 9 | trait InstrumentedActor extends Actor with ActorLogging { 10 | override def preRestart(reason: Throwable, message: Option[Any]) { 11 | log.error(self + " restarted due to message=%s, exception=%s".format(message.getOrElse("unspecified"), reason)) 12 | log.debug("stack trace: " + reason.getStackTrace.mkString("\n")) 13 | super.preRestart(reason, message) 14 | } 15 | 16 | /** 17 | * A nice readable name for this actor (removing bad symbols) 18 | */ 19 | override def toString = "%s(%s)".format(getClass.getSimpleName, self.path) 20 | } -------------------------------------------------------------------------------- /common/lib/org.mavlink.library.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/lib/org.mavlink.library.jar -------------------------------------------------------------------------------- /common/lib/org.mavlink.util.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/lib/org.mavlink.util.jar -------------------------------------------------------------------------------- /common/src/main/protobuf/webapi.proto: -------------------------------------------------------------------------------- 1 | ../../../../droneapi-protobuf/src/webapi.proto -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/AkkaTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.ActorRef 4 | import akka.util.Timeout 5 | import scala.concurrent.duration._ 6 | import akka.pattern.ask 7 | import akka.actor.Identify 8 | import scala.concurrent.Future 9 | 10 | object AkkaTools { 11 | 12 | // Wait until the specified actor is responding to msgs 13 | def waitAlive(actor: ActorRef): Future[Any] = { 14 | implicit val timeout = Timeout(30 second) 15 | actor ? Identify(0L) 16 | } 17 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/DebuggableActor.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.Actor 4 | import akka.actor.ActorLogging 5 | import com.geeksville.util.AnalyticsService 6 | 7 | case object GetDebugInfo 8 | 9 | /** 10 | * Returns debugging information about this actor. Typically either as a string or XML. 11 | * You can assume that the recipient will probably toString the response (but not necessarily) 12 | */ 13 | case class DebugInfoResponse(info: Any) 14 | 15 | trait DebuggableActor extends Actor with ActorLogging with UncaughtExceptionActor { 16 | 17 | protected def debuggingInfo: Any = toString 18 | 19 | override def preRestart(reason: Throwable, message: Option[Any]) { 20 | log.error(s"RESTARTING $this due to $reason, message=$message") 21 | AnalyticsService.reportException(s"RESTARTING $this, message=$message", reason) 22 | super.preRestart(reason, message) 23 | } 24 | 25 | override def postStop() { 26 | log.warning(s"postStop on $this") 27 | super.postStop() 28 | } 29 | 30 | override def unhandled(message: Any): Unit = { 31 | message match { 32 | case GetDebugInfo ⇒ 33 | println(s"Replying to $sender with $debuggingInfo") 34 | sender ! DebugInfoResponse(debuggingInfo) 35 | case _ ⇒ 36 | super.unhandled(message) 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/EventStreamDebugger.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.{ Actor, DeadLetter, Props } 4 | import akka.actor.ActorLogging 5 | import akka.actor.UnhandledMessage 6 | import org.mavlink.messages.MAVLinkMessage 7 | 8 | class EventStreamDebugger extends Actor with ActorLogging with DebuggableActor { 9 | private val messagesToIgnore = List(classOf[MAVLinkMessage]) 10 | 11 | context.system.eventStream.subscribe(self, classOf[DeadLetter]) 12 | context.system.eventStream.subscribe(self, classOf[UnhandledMessage]) 13 | 14 | def receive = { 15 | case d: DeadLetter => log.error(s"DeadLetter: $d") 16 | case d: UnhandledMessage => 17 | // There are a few message types we expect to be ignored by most 18 | d.message match { 19 | case _: MAVLinkMessage => 20 | case GetDebugInfo => 21 | case _ => 22 | log.error(s"UnhandledMessage: $d") 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/InstrumentedActor.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.Actor 4 | import akka.actor.ActorLogging 5 | 6 | /* 7 | object Context { 8 | def system = MockAkka 9 | } 10 | */ 11 | 12 | object InstrumentedActor { 13 | type Receiver = PartialFunction[Any, Unit] 14 | } 15 | 16 | /** 17 | * Try to make scala actors look as much like akka actors as possible 18 | */ 19 | trait InstrumentedActor extends DebuggableActor { 20 | import InstrumentedActor._ 21 | 22 | /** 23 | * The replacement for the akka receive method 24 | */ 25 | def onReceive: Receiver 26 | 27 | override def receive = onReceive 28 | 29 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/MockAkka.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import com.geeksville.logback.Logger 4 | import com.geeksville.logback.Logging 5 | import scala.collection.mutable.HashSet 6 | import akka.actor.ActorSystem 7 | import com.typesafe.config.ConfigFactory 8 | import com.typesafe.config.Config 9 | 10 | object MockAkka extends Logging { 11 | 12 | // The system event stream 13 | val eventStream = new EventStream 14 | 15 | /** 16 | * If you'd like to use a non standard config (i.e. android) you can set configOverride early in application start 17 | */ 18 | var configOverride: Option[Config] = None 19 | 20 | // For some platforms (android) it is useful to pass in a non default class loader 21 | var classLoader = getClass.getClassLoader 22 | 23 | lazy val config = { 24 | //println(s"GETTING CONFIG: $configOverride") 25 | configOverride.getOrElse(ConfigFactory.load(classLoader)) 26 | } 27 | 28 | private var currentSystem: Option[ActorSystem] = None 29 | 30 | /// Create a new akka system as needed 31 | def system = currentSystem.getOrElse { 32 | currentSystem = Some(ActorSystem("mockakka", config, classLoader)) 33 | currentSystem.get 34 | } 35 | 36 | def shutdown() { 37 | system.shutdown() 38 | system.awaitTermination() 39 | currentSystem = None // If we use akka again we'll need to start from scratch 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/TimesteppedActor.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor.Actor 4 | import akka.actor.PoisonPill 5 | import scala.concurrent.duration._ 6 | 7 | /** 8 | * This is an Actor mixin that runs doNextStep periodically 9 | */ 10 | trait TimesteppedActor extends Actor { 11 | import context._ 12 | 13 | private case object SimNext 14 | 15 | def numPoints: Int 16 | def interval: Double 17 | 18 | protected var numRemaining = numPoints 19 | 20 | /// What step are we currently on? 21 | def currentStep = numPoints - numRemaining 22 | 23 | private def scheduleNext() = context.system.scheduler.scheduleOnce(interval seconds, self, SimNext) 24 | 25 | // Start our sim 26 | scheduleNext() 27 | 28 | protected def doNextStep(): Unit 29 | 30 | abstract override def receive = ({ 31 | case SimNext => 32 | if (numRemaining == 0) 33 | self ! PoisonPill 34 | else { 35 | doNextStep() 36 | 37 | numRemaining -= 1 38 | scheduleNext() 39 | } 40 | }: PartialFunction[Any, Unit]).orElse(super.receive) 41 | } 42 | 43 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/akka/UncaughtExceptionActor.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.akka 2 | 3 | import akka.actor._ 4 | import com.geeksville.util.AnalyticsService 5 | 6 | /** 7 | * For uncaught exceptions report via our analytics plugin. 8 | * 9 | * No need to mixin this actor directly - you probably want DebuggableActor instead 10 | */ 11 | trait UncaughtExceptionActor extends Actor { 12 | self: ActorLogging => 13 | 14 | override def preRestart(reason: Throwable, message: Option[Any]) { 15 | super.preRestart(reason, message) 16 | log.error(reason, "Unhandled exception for message: {}", message) 17 | AnalyticsService.reportException(message.getOrElse("unknown").toString, reason) 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/apiproxy/GCSCallback.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.apiproxy 2 | 3 | trait GCSCallback { 4 | /// Dear GCS, please send this packet 5 | def sendMavlink(b: Array[Byte]) 6 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/flight/EventBusVehicleReceiver.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.flight 2 | 3 | import com.geeksville.mavlink.HeartbeatMonitor 4 | import com.geeksville.mavlink.MavlinkEventBus 5 | 6 | /** 7 | * This is a mixin that can be added to VehicleClient if you'd like to automatically listen to the global event bus to find packets 8 | * destined to this vehicle. 9 | */ 10 | trait EventBusVehicleReceiver extends VehicleClient { 11 | // Default to listening to all traffic until we know the id of our vehicle 12 | // This lets the vehicle model receive messages from its vehicle... 13 | private var subscriber = MavlinkEventBus.subscribe(self, targetOverride.getOrElse(-1)) 14 | 15 | override protected def onHeartbeatFound() { 16 | if (!targetOverride.isDefined) { 17 | // We didn't previously have any particular sysId filter installed. Now that we know our vehicle 18 | // we can be more selective. Resubscribe with the new system id 19 | MavlinkEventBus.removeSubscription(subscriber) 20 | subscriber = MavlinkEventBus.subscribe(self, targetSystem) 21 | } 22 | super.onHeartbeatFound() 23 | } 24 | 25 | override def postStop() { 26 | MavlinkEventBus.removeSubscription(subscriber) 27 | super.postStop() 28 | } 29 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/flight/FlightLead.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.flight 2 | 3 | // Standard akka imports 4 | import scala.concurrent.duration._ 5 | import com.geeksville.mavlink._ 6 | import com.geeksville.flight._ 7 | import com.geeksville.akka.InstrumentedActor 8 | import com.geeksville.util.Counted 9 | import org.mavlink.messages.MAVLinkMessage 10 | import com.geeksville.logback.Logging 11 | import com.geeksville.akka.MockAkka 12 | 13 | /** 14 | * Listen for GPS Locations on the event bus, and drive our simulated vehicle 15 | */ 16 | class FlightLead(sysId: Int = FlightLead.systemId) extends InstrumentedActor with VehicleSimulator with HeartbeatSender with SendsMavlinkToEventbus { 17 | 18 | private val throttle = new Counted(10) 19 | 20 | override def systemId = sysId 21 | 22 | MockAkka.eventStream.subscribe(self, { e: Any => e.isInstanceOf[Location] }) 23 | 24 | def onReceive = { 25 | case l: Location => 26 | sendMavlink(makePosition(l)) 27 | sendMavlink(makeGPSRaw(l)) 28 | throttle { i => 29 | val msg = "Emitted %d points...".format(i) 30 | log.info(msg) 31 | sendMavlink(makeStatusText(msg)) 32 | sendMavlink(makeSysStatus()) 33 | } 34 | } 35 | } 36 | object FlightLead { 37 | 38 | /** 39 | * We use a systemId 2, because the ardupilot is normally on 1. 40 | */ 41 | val systemId: Int = 2 42 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/flight/HeartbeatSender.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.flight 2 | 3 | import com.geeksville.flight._ 4 | import scala.concurrent.duration._ 5 | import scala.language.postfixOps 6 | import org.mavlink.messages.ardupilotmega._ 7 | import org.mavlink.messages._ 8 | import java.util.GregorianCalendar 9 | import com.geeksville.mavlink.MavlinkEventBus 10 | import com.geeksville.akka.InstrumentedActor 11 | import com.geeksville.mavlink.SendYoungest 12 | import com.geeksville.util.ThreadTools._ 13 | import akka.actor.Actor 14 | import akka.actor.Cancellable 15 | 16 | // Heartbeat sender expects its mixin to be able to send this message 17 | case class SendMessage(msg: MAVLinkMessage) 18 | 19 | /** 20 | * A mixin that adds periodic sending of heartbeats 21 | * 22 | */ 23 | trait HeartbeatSender extends Actor with VehicleSimulator { 24 | // FIXME - the following should work but does not: self: VehicleSimulator => 25 | 26 | import context._ 27 | 28 | // Send a heartbeat every few seconds 29 | var heartbeatSender = { 30 | val msg = SendMessage(heartbeat) 31 | context.system.scheduler.schedule(1 seconds, 3 seconds, self, msg) 32 | } 33 | 34 | override def postStop() { 35 | //println("cancelling heartbeat sender") 36 | heartbeatSender.cancel() 37 | super.postStop() 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/flight/VehicleListener.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.flight 2 | 3 | import com.geeksville.akka.InstrumentedActor 4 | 5 | /** 6 | * Used to eavesdrop on location/state changes for our vehicle 7 | */ 8 | abstract class VehicleListener(val v: VehicleModel) extends InstrumentedActor { 9 | 10 | val subscription = v.eventStream.subscribe(this) 11 | 12 | override def postStop() { 13 | v.eventStream.removeSubscription(subscription) 14 | super.postStop() 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/flight/WaypointsForMap.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.flight 2 | 3 | /** 4 | * A mixin that adds waypointsForMap 5 | */ 6 | trait WaypointsForMap { 7 | 8 | def waypoints: Seq[Waypoint] 9 | 10 | /** 11 | * An expanded version of waypoints (i.e. resolving jumps), but removing any waypoints that don't have position 12 | */ 13 | def waypointsForMap = { 14 | var index = 0 15 | val wpCopy = waypoints 16 | val inspected = Array.fill(wpCopy.size)(false) 17 | 18 | // No matter what we never want to emit more waypoints than we started with 19 | (0 until wpCopy.size).flatMap { loopNum => 20 | if (index >= waypoints.size) 21 | None 22 | else if (!inspected(index)) { 23 | val wp = waypoints(index) 24 | inspected(index) = true 25 | 26 | if (wp.isJump) { 27 | index = wp.jumpSequence 28 | None 29 | } else { 30 | index += 1 31 | if (!wp.isForMap) 32 | None 33 | else 34 | Some(wp) 35 | } 36 | } else { 37 | // Already seen it 38 | index += 1 39 | None 40 | } 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/gcsapi/ArrayAdapter.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import com.ridemission.rest.JArray 4 | import com.ridemission.rest.JValue 5 | import com.ridemission.rest.JsonConverters._ 6 | import com.ridemission.rest.JObject 7 | 8 | /** 9 | * Exposes N children indexed by int. 10 | * i.e. we match member names that look like "24" 11 | * 12 | * No GCS specific code here - someday I'd like to reuse this somewhere else 13 | */ 14 | class ArrayAdapter(val children: Seq[SmallAPI]) extends HierarchicalAdapter { 15 | 16 | /** 17 | * If the user wants something in a child, delegate it to the child - otherwise handle it here 18 | */ 19 | def getChild(memberName: String): Option[(String, SmallAPI)] = { 20 | 21 | val (m, rest) = splitAtDot(memberName) 22 | val index = m.toInt 23 | val child = children(index) 24 | Some(rest -> child) 25 | } 26 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/gcsapi/GCSModel.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import com.geeksville.flight.VehicleModel 4 | 5 | /** 6 | * The top level operations all GCSes must support 7 | */ 8 | trait GCSModel { 9 | /** 10 | * All the vehicles we know about 11 | */ 12 | def vehicles: Seq[VehicleModel] 13 | 14 | // FIXME - add UI components/options 15 | } 16 | 17 | /** 18 | * A placeholder version of the GCS model until something more real exists 19 | */ 20 | class TempGCSModel(v: VehicleModel) extends GCSModel { 21 | val vehicles = Seq(v) 22 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/gcsapi/MapAdapter.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.gcsapi 2 | 3 | import com.ridemission.rest.JArray 4 | import com.ridemission.rest.JValue 5 | import com.ridemission.rest.JsonConverters._ 6 | import com.ridemission.rest.JObject 7 | 8 | /** 9 | * Exposes child SmallAPI instances, with dots to separate the names of children 10 | * 11 | * No GCS specific code here - someday I'd like to reuse this somewhere else 12 | */ 13 | trait MapAdapter extends HierarchicalAdapter { 14 | def children: Map[String, SmallAPI] = Map() 15 | 16 | /** 17 | * If the user wants something in a child, delegate it to the child - otherwise handle it here 18 | */ 19 | def getChild(memberName: String): Option[(String, SmallAPI)] = { 20 | val (m, rest) = splitAtDot(memberName) 21 | 22 | val child = children(m) 23 | Some(rest -> child) 24 | } 25 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/logback/Logging.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2011 Weigle Wilczek GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.geeksville.logback 17 | 18 | /** 19 | * Mixin providing a Logger for the type mixed into. 20 | */ 21 | trait Logging { 22 | 23 | /** 24 | * Logger for the type mixed into. 25 | */ 26 | protected lazy val logger = Logger(this.getClass) 27 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/logback/MuteAllFilter.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.logback 2 | 3 | import ch.qos.logback.core.filter.Filter 4 | import ch.qos.logback.classic.spi.ILoggingEvent 5 | import ch.qos.logback.core.spi.FilterReply 6 | import scala.reflect.BeanProperty 7 | import ch.qos.logback.classic.Level 8 | 9 | /** 10 | * If mute is set to true, then turn off all logging (useful to globally toggle logs at runtime) 11 | */ 12 | class MuteAllFilter extends Filter[ILoggingEvent] { 13 | 14 | override def decide(e: ILoggingEvent) = if (MuteAllFilter.mute) FilterReply.DENY else FilterReply.ACCEPT 15 | } 16 | 17 | object MuteAllFilter { 18 | var mute = false 19 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/logback/NameLevelFilter.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.logback 2 | 3 | import ch.qos.logback.core.filter.Filter 4 | import ch.qos.logback.classic.spi.ILoggingEvent 5 | import ch.qos.logback.core.spi.FilterReply 6 | import scala.reflect.BeanProperty 7 | import ch.qos.logback.classic.Level 8 | 9 | /** 10 | * If a particular package/classname matches, the decide logging based on the level of the message 11 | */ 12 | class NameLevelFilter extends Filter[ILoggingEvent] { 13 | 14 | @BeanProperty 15 | var prefix = "" 16 | 17 | @BeanProperty 18 | var minLevel = Level.ALL 19 | 20 | override def decide(e: ILoggingEvent) = { 21 | if (!e.getLoggerName.startsWith(prefix)) 22 | FilterReply.NEUTRAL 23 | else if (e.getLevel.isGreaterOrEqual(minLevel)) 24 | FilterReply.ACCEPT // Level is sufficient - show it 25 | else 26 | FilterReply.DENY // veto 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/CanSendMavlink.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import org.mavlink.messages.MAVLinkMessage 4 | 5 | /** 6 | * A small interface which is common to all objects that have a handlePacket method (probably just VehicleSimulator) 7 | */ 8 | trait CanSendMavlink { 9 | /** 10 | * Sends an outgoing packet 11 | * m must be a SendYoungest or a MAVLinkMessage 12 | */ 13 | protected def handlePacket(m: Any) 14 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/LastSeenPackets.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import com.geeksville.akka.InstrumentedActor 4 | import org.mavlink.messages.MAVLinkMessage 5 | import org.mavlink.messages.ardupilotmega._ 6 | import LogIncomingMavlink._ 7 | import scala.collection.mutable.HashMap 8 | 9 | /** 10 | * Keep a map of the most recent packet of any received type 11 | */ 12 | class LastSeenPackets(sysId: Int) extends InstrumentedActor { 13 | MavlinkEventBus.subscribe(self, sysId) 14 | 15 | val recent = HashMap[Int, MAVLinkMessage]() 16 | 17 | def toLongString = recent.values.mkString("Recent packets:\n", "\n", "\n") 18 | 19 | def onReceive = { 20 | case msg: MAVLinkMessage => 21 | recent(msg.messageType) = msg 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/LogIncomingMavlink.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import com.geeksville.akka.InstrumentedActor 4 | import org.mavlink.messages.MAVLinkMessage 5 | import org.mavlink.messages.ardupilotmega._ 6 | import LogIncomingMavlink._ 7 | 8 | class LogIncomingMavlink(sysId: Int, allow: MAVLinkMessage => Boolean = allowDefault) extends InstrumentedActor { 9 | MavlinkEventBus.subscribe(self, sysId) 10 | 11 | def onReceive = { 12 | case msg: msg_statustext => 13 | log.info("Rcv" + msg.sysId + ": " + msg.getText) 14 | 15 | case msg: MAVLinkMessage => 16 | def str = "Rcv" + msg.sysId + ": " + msg 17 | if (allow(msg)) 18 | log.info(str) 19 | else 20 | log.debug(str) 21 | } 22 | } 23 | 24 | object LogIncomingMavlink { 25 | val boringMessages: Set[Class[_]] = Set( 26 | classOf[msg_heartbeat], 27 | classOf[msg_sys_status], 28 | classOf[msg_hwstatus], 29 | classOf[msg_rc_channels_scaled], 30 | classOf[msg_rc_channels_raw], 31 | classOf[msg_servo_output_raw], 32 | classOf[msg_meminfo], 33 | classOf[msg_raw_imu], 34 | classOf[msg_raw_pressure], 35 | classOf[msg_gps_raw_int], 36 | classOf[msg_scaled_pressure]) 37 | 38 | def allowDefault(msg: MAVLinkMessage) = !boringMessages.contains(msg.getClass) 39 | def allowNothing(msg: MAVLinkMessage) = false 40 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/MavlinkConstants.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | /** 4 | * Constants that are missing from the auto generated files 5 | */ 6 | trait MavlinkConstants { 7 | val MAVLINK_TYPE_CHAR = 0 8 | val MAVLINK_TYPE_UINT8_T = 1 9 | val MAVLINK_TYPE_INT8_T = 2 10 | val MAVLINK_TYPE_UINT16_T = 3 11 | val MAVLINK_TYPE_INT16_T = 4 12 | val MAVLINK_TYPE_UINT32_T = 5 13 | val MAVLINK_TYPE_INT32_T = 6 14 | val MAVLINK_TYPE_UINT64_T = 7 15 | val MAVLINK_TYPE_INT64_T = 8 16 | val MAVLINK_TYPE_FLOAT = 9 17 | val MAVLINK_TYPE_DOUBLE = 10 18 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/MavlinkEventBus.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import org.mavlink.messages.MAVLinkMessage 4 | import com.geeksville.akka.EventStream 5 | import com.geeksville.logback.Logging 6 | import akka.actor.Actor 7 | import akka.actor.ActorRef 8 | 9 | object MavlinkEventBus extends EventStream with Logging { 10 | 11 | /** 12 | * @param sysId use -1 for any system 13 | */ 14 | def subscribe(a: ActorRef, sysId: Int) = { 15 | def interested(ev: Any) = { 16 | val r = ev match { 17 | case SendYoungest(m) if (m.sysId == sysId) || (sysId == -1) => true 18 | case m: MAVLinkMessage if (m.sysId == sysId) || (sysId == -1) => true 19 | case _ => false 20 | } 21 | 22 | //logger.debug("%s: interest in %s (myId=%d) is %s".format(a, ev, sysId, r)) 23 | r 24 | } 25 | 26 | super.subscribe(a, interested _) 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/MavlinkReceiver.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import org.mavlink.messages.MAVLinkMessage 4 | 5 | /** 6 | * published on our eventbus when a new packet arrives from the outside world 7 | */ 8 | 9 | /** 10 | * Common code for any gateway that receives mavlink messages into our actor system 11 | */ 12 | trait MavlinkReceiver { 13 | 14 | /** 15 | * For now we pipe all our notifications through the system event stream - we might refine this later 16 | */ 17 | // val destEventBus = MavlinkEventBus 18 | 19 | /** 20 | * Where msg is a SendYoungest or a MAVLinkMessage 21 | */ 22 | protected def handleIncomingPacket(msg: Any) { 23 | assert(msg != null) 24 | MavlinkEventBus.publish(msg) 25 | } 26 | 27 | } 28 | 29 | /** 30 | * Use this mixin if you want any mavlink sent by an object to be automatically published on the local eventbus 31 | */ 32 | trait SendsMavlinkToEventbus extends MavlinkReceiver with CanSendMavlink { 33 | /// Just forward anything we send to the event bus 34 | override def handlePacket(a: Any) = handleIncomingPacket(a) 35 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/MavlinkTCP.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import java.net._ 4 | import com.geeksville.util.ThreadTools 5 | import com.geeksville.akka.InstrumentedActor 6 | import java.io.BufferedInputStream 7 | import java.io.BufferedOutputStream 8 | 9 | object MavlinkTCP { 10 | 11 | /** 12 | * Initiates a connection to TCP server 13 | */ 14 | def connect(destHostName: String, destPortNumber: Int) = { 15 | 16 | // These must be lazy - to ensure we don't do networking in the main thread (an android restriction) 17 | lazy val socket = { 18 | val r = new Socket(destHostName, destPortNumber) 19 | 20 | r.setReceiveBufferSize(32768) 21 | r.setTcpNoDelay(true) 22 | r 23 | } 24 | lazy val in = { 25 | val s = socket.getInputStream 26 | assert(s != null) 27 | new BufferedInputStream(s, 512) 28 | } 29 | lazy val out = { 30 | val s = socket.getOutputStream 31 | assert(s != null) 32 | new BufferedOutputStream(s, 512) 33 | } 34 | 35 | new MavlinkStream(out, in) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/MavlinkUtils.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import org.mavlink.IMAVLinkMessage 4 | import org.mavlink.messages.MAVLinkMessageFactory 5 | import org.mavlink.messages.MAVLinkMessage 6 | 7 | object MavlinkUtils { 8 | 9 | /// A more verbose tostring for mavlink msgs 10 | def toString(m: MAVLinkMessage) = { 11 | s"$m sysId=${m.sysId} compId=${m.componentId}" 12 | } 13 | 14 | def bytesToPacket(msg: Array[Byte]): Option[MAVLinkMessage] = { 15 | 16 | //log.info("Processing packet from " + remote.get) 17 | 18 | msg match { 19 | case Array(start, payLength, packSeq, sysId, compId, msgId, payload @ _*) => 20 | if (start == IMAVLinkMessage.MAVPROT_PACKET_START_V10) { 21 | val packet = MAVLinkMessageFactory.getMessage(msgId & 0xff, sysId & 0xff, compId & 0xff, payload.take(payLength).toArray) 22 | //log.debug("Mav rx sysId=%d: %s".format(sysId & 0xff, packet)) 23 | Option(packet) 24 | } else { 25 | //log.error("Ignoring bad MAVLink packet") 26 | None 27 | } 28 | case _ => 29 | //log.error("Ignoring bad match") 30 | None 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/TlogStreamReceiver.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.mavlink 2 | 3 | import java.io.BufferedInputStream 4 | import java.io.InputStream 5 | 6 | object TlogStreamReceiver { 7 | /** 8 | * Read from a tlog in the classpath, i.e. "/path/file.ext" 9 | */ 10 | def open(s: InputStream, speedup: Double = 1.0, autoStart: Boolean = true) = { 11 | println(s"Opened $s " + s.available) 12 | new MavlinkStreamReceiver(s, tlogSpeedup = Some(speedup), autoStart = autoStart) 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/mavlink/package.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville 2 | 3 | package object mavlink { 4 | 5 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/AnalyticsService.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | /** 4 | * Extend/implement this trait for the analytics engine of your choice 5 | */ 6 | trait AnalyticsAdapter { 7 | def reportException(msg: String, ex: Throwable) 8 | 9 | // Add interesting information which will be attached _if_ we throw an error 10 | def addBreadcrumb(key: String, value: String) {} 11 | } 12 | 13 | /** 14 | * Just reports exceptions via stdout 15 | */ 16 | class SimpleAnalyticsAdapter extends AnalyticsAdapter { 17 | def reportException(msg: String, ex: Throwable) { 18 | println(s"Exception occurred (msg=$msg): $ex") 19 | } 20 | } 21 | 22 | object AnalyticsService { 23 | 24 | /** 25 | * Assign to this to select a non standard handler 26 | */ 27 | var handler: AnalyticsAdapter = new SimpleAnalyticsAdapter 28 | 29 | /** 30 | * Report an exception to our analytics 31 | */ 32 | def reportException(msg: String, ex: Throwable) = handler.reportException(msg, ex) 33 | 34 | def addBreadcrumb(key: String, value: String) = handler.addBreadcrumb(key, value) 35 | 36 | /** 37 | * Silently report any exceptions that occur in a block of code. 38 | */ 39 | def wrap(block: => Unit) = 40 | { 41 | try { 42 | block 43 | } catch { 44 | case ex: Throwable => 45 | reportException("wrapped", ex) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/Base32.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | /** 4 | * Utilities for encoding in base32 5 | */ 6 | object Base32 { 7 | 8 | private val symbols = ('a' to 'z') ++ ('2' to '7') 9 | private val symToVal = Map(symbols.zipWithIndex: _*) 10 | 11 | def encode(nIn: Long) = { 12 | var n = nIn 13 | var out = List[Char]() 14 | while (n != 0) { 15 | val c = symbols((n & 0x1f).toInt) 16 | n = (n >> 5) & 0x07ffffffffffffffL 17 | out = c :: out 18 | } 19 | out.mkString 20 | } 21 | 22 | def decode(s: String) = { 23 | var n = 0L 24 | s.foreach { c => 25 | n = (n << 5) | symToVal(c) 26 | } 27 | n 28 | } 29 | 30 | /* 31 | def main(a: Array[String]) { 32 | println(encode(4403L)) 33 | println(encode(1234567890)) 34 | println(decode(encode(4403L))) 35 | println(decode(encode(1234567890))) 36 | } 37 | * */ 38 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/ByteOnlyInputStream.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.io._ 4 | 5 | /** 6 | * Read an input stream byte by byte (never doing more efficient multibyte reads). 7 | * Useful for working with buggy RXTX code 8 | */ 9 | class ByteOnlyInputStream(val s: InputStream) extends InputStream { 10 | override def read() = s.read() 11 | 12 | override def available() = s.available() 13 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/Counted.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | /// A helper class that calls a callback every nth invocation 4 | /// 5 | /// To use: throttled = new Counted(1000); throttled { i => some code } 6 | class Counted(val interval: Int) { 7 | private var count = 0 8 | 9 | def apply(fn: Int => Unit) { 10 | count += 1 11 | if (count % interval == 0) 12 | fn(count) 13 | } 14 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/DateTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.util.TimeZone 4 | import java.text.SimpleDateFormat 5 | import java.util.Date 6 | 7 | object DateTools { 8 | 9 | val utcTZ = TimeZone.getTimeZone("UTC"); 10 | val df8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") 11 | 12 | df8601.setTimeZone(utcTZ) 13 | 14 | def toISO8601(d: Date) = df8601.format(d) 15 | def fromISO8601(d: String) = df8601.parse(d) 16 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/DebugInputStream.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.io._ 4 | 5 | /** 6 | * A debugging tool to let you watch bytes as they are read 7 | */ 8 | class DebugInputStream(s: InputStream) extends FilterInputStream(s) { 9 | override def read() = { 10 | val b = super.read() 11 | // if (b != -1) 12 | printf("Rx %02x\n", b) 13 | b 14 | } 15 | 16 | override def read(b: Array[Byte], off: Int, len: Int) = { 17 | val r = super.read(b, off, len) 18 | if (r >= 0) 19 | printf("Rx " + b.drop(off).take(len).map { n => "%02x".format(n) }.mkString(",") + "\n") 20 | r 21 | } 22 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/Gravatar.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.util._ 4 | import java.io._ 5 | import java.security._ 6 | 7 | object Gravatar { 8 | private def hex(array: Array[Byte]) = array.map { b => "%02x".format(b) }.mkString 9 | 10 | private def md5Hex(message: String) = { 11 | val md = MessageDigest.getInstance("MD5") 12 | val r = hex(md.digest(message.getBytes("CP1252"))) 13 | r 14 | } 15 | 16 | private def emailHash(email: String) = md5Hex(email.trim.toLowerCase) 17 | 18 | def profileUrl(email: String) = s"http://www.gravatar.com/${emailHash(email)}" 19 | 20 | def avatarImageUrl(email: String) = s"http://www.gravatar.com/avatar/${emailHash(email)}.jpg" 21 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/HeadInputStream.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.io._ 4 | 5 | /// An input stream wrapper which will return maxBytes of data 6 | class HeadInputStream(in: InputStream, maxBytes: Int) extends FilterInputStream(in) { 7 | var numLeft = maxBytes 8 | 9 | /// @return number of chars that can be read at this time (or -1 for eof) 10 | private def decLeft(d: Int) = { 11 | assert(d >= 0) 12 | 13 | val m = math.min(numLeft, d) 14 | 15 | numLeft -= m 16 | 17 | if (m == 0) 18 | -1 // eof 19 | else 20 | m 21 | } 22 | 23 | override def available = math.min(super.available, numLeft) 24 | 25 | /// We don't support mark (for now) 26 | override def markSupported = false 27 | 28 | override def read() = { 29 | val m = decLeft(1) 30 | if (m > 0) 31 | super.read() 32 | else 33 | m 34 | } 35 | 36 | override def read(b: Array[Byte], off: Int, len: Int) = { 37 | val m = decLeft(len) 38 | if (m > 0) 39 | super.read(b, off, m) 40 | else 41 | m 42 | } 43 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/NetTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.net.NetworkInterface 4 | import scala.collection.JavaConverters._ 5 | import java.net.Inet4Address 6 | import java.net.SocketException 7 | 8 | object NetTools { 9 | 10 | lazy val localIPAddresses = { 11 | val interfaces = try { 12 | NetworkInterface.getNetworkInterfaces().asScala 13 | } catch { 14 | case ex: SocketException => 15 | // Android sometimes fails to parse some network names and barfs internally 16 | Seq[NetworkInterface]().toIterator 17 | } 18 | val iface = interfaces.filter { i => i.isUp && !i.isLoopback && !i.isVirtual } 19 | iface.flatMap { i => 20 | val addrs = i.getInetAddresses.asScala 21 | addrs.flatMap { a => 22 | a match { 23 | case x: Inet4Address => Some(x.getHostAddress) 24 | case _ => None 25 | } 26 | } 27 | }.toSeq 28 | } 29 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/OSTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | /// Utilities for doing OS specific operations 4 | object OSTools { 5 | 6 | /// Check for Android but without using any android libs 7 | def isAndroid = System.getProperty("java.vm.name") == "Dalvik" 8 | 9 | def osName = System.getProperty("os.name").toLowerCase 10 | def isWindows = osName.contains("win") 11 | def isLinux = osName.contains("linux") 12 | def isMac = osName.contains("mac") 13 | 14 | def runtime = Runtime.getRuntime 15 | 16 | /// Create and start a child process 17 | def exec(cmdArgs: String*) = runtime.exec(cmdArgs.toArray) 18 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/PartialFunctionTools.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | object PartialFunctionTools { 4 | 5 | /** 6 | * Given two partial functions, construct a partial function that calls both of them 7 | * whenever they are defined 8 | */ 9 | def callBoth[A](p1: PartialFunction[A, Unit], p2: PartialFunction[A, Unit]) = new PartialFunction[A, Unit] { 10 | def isDefinedAt(x: A) = p1.isDefinedAt(x) || p2.isDefinedAt(x) 11 | 12 | def apply(x: A) = { 13 | if (p1.isDefinedAt(x)) 14 | p1.apply(x) 15 | if (p2.isDefinedAt(x)) 16 | p2.apply(x) 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/QueueInputStream.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import scala.collection.mutable.Queue 4 | import java.io.InputStream 5 | 6 | /** 7 | * This is a fairly specialized input stream that pulls data from a scala queue. 8 | * If the queue ever becomes empty, available will start returning 0. 9 | */ 10 | class QueueInputStream(val queue: Queue[java.lang.Byte]) extends InputStream { 11 | override def read(): Int = { 12 | if (queue.isEmpty) 13 | -1 14 | else 15 | (queue.dequeue().toInt & 0xff) 16 | } 17 | 18 | override def available() = queue.size 19 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/RingBuffer.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import scala.collection.mutable._ 4 | 5 | /// A buffer that guarantees a maximum # of elements 6 | /// If we exceed that count we discard old elements 7 | /// Note: Not actually implemented as a ring buffer 8 | /// but other than implicitly dropping the oldest items it is similar 9 | class RingBuffer[A](val maxCount: Int) extends BufferProxy[A] { 10 | override val self = new ListBuffer[A] 11 | 12 | override def +=(x: A) = { makeSpace(); super.+=(x) } 13 | 14 | private def makeSpace() { 15 | val todrop = math.max(length - maxCount + 1, 0) 16 | trimStart(todrop) 17 | } 18 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/SimplePublisher.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import scala.collection.mutable.Subscriber 4 | 5 | /** 6 | * Simplified version of scala.collection.mutable.Publisher which is much 7 | * more efficient. 8 | */ 9 | trait SimplePublisher[Evt] { 10 | 11 | type Pub <: SimplePublisher[Evt] 12 | type Sub = Subscriber[Evt, Pub] 13 | 14 | /** 15 | * The publisher itself of type `Pub'. Implemented by a cast from `this' here. 16 | * Needs to be overridden if the actual publisher is different from `this'. 17 | */ 18 | protected val self: Pub = this.asInstanceOf[Pub] 19 | 20 | private var subscribers = collection.immutable.ListSet.empty[Sub] 21 | 22 | def subscribe(sub: Sub) { subscribers += sub } 23 | def removeSubscription(sub: Sub) { subscribers -= sub } 24 | def removeSubscriptions() { subscribers = collection.immutable.ListSet.empty } 25 | 26 | def publish(event: Evt) { 27 | subscribers.foreach(_.notify(self, event)) 28 | } 29 | 30 | /** 31 | * Checks if two publishers are structurally identical. 32 | * 33 | * @return true, iff both publishers contain the same sequence of elements. 34 | */ 35 | override def equals(obj: Any): Boolean = obj match { 36 | case that: SimplePublisher[_] => subscribers == that.subscribers 37 | case _ => false 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/TCPListener.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import java.net.ServerSocket 4 | import java.net.Socket 5 | import java.net.SocketException 6 | 7 | /** 8 | * Listens on a particular TCP port number, firing up connection handers when connections arrive 9 | */ 10 | class TCPListener(val portNum: Int, val handleConnection: Socket => Unit) { 11 | val queueLen = 10 12 | private val serverSocket = new ServerSocket(portNum, queueLen) 13 | private val listenerThread = ThreadTools.createDaemon("RESTServe")(readerFunct) 14 | 15 | listenerThread.start() 16 | 17 | /// Shut down this server 18 | def close() { 19 | serverSocket.close() // Should cause the thread to die 20 | } 21 | 22 | private def readerFunct() { 23 | try { 24 | while (true) { 25 | val socket = serverSocket.accept() 26 | 27 | handleConnection(socket) 28 | } 29 | } catch { 30 | case x: SocketException => 31 | println("REST socket has been closed, exiting receiver...") 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/UnbufferedSource.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | import scala.io.Source 4 | import java.io.{ InputStream, Reader, InputStreamReader } 5 | import Source.DefaultBufSize 6 | 7 | /** 8 | * A source that just reads a reader - with no buffering 9 | */ 10 | class UnbufferedSource(reader: Reader) extends Source { 11 | private val isWindows = false // FIXME - add back if we ever care 12 | private val eofChar: Int = (if (isWindows) 'Z' else 'D') - 'A' + 1 13 | 14 | override val iter = { 15 | Iterator continually (reader.read()) takeWhile { c => c != -1 && c != eofChar } map (_.toChar) 16 | } 17 | } 18 | 19 | /** 20 | * A source that just reads a input stream - with no buffering 21 | */ 22 | class UnbufferedStreamSource(reader: InputStream) extends Source { 23 | override val iter = { 24 | Iterator continually (reader.read()) takeWhile { c => c != -1 } map (_.toChar) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/scala/com/geeksville/util/Using.scala: -------------------------------------------------------------------------------- 1 | package com.geeksville.util 2 | 3 | /** 4 | * C++ style using 5 | * http://stackoverflow.com/questions/2207425/what-automatic-resource-management-alternatives-exists-for-scala 6 | * 7 | * Example: 8 | * 9 | * using(new BufferedReader(new FileReader("file"))) { r => 10 | * var count = 0 11 | * while (r.readLine != null) count += 1 12 | * println(count) 13 | * } 14 | */ 15 | object Using { 16 | 17 | def using[T <: { def close() }, ResType](resource: T)(block: T => ResType) = 18 | { 19 | try { 20 | block(resource) 21 | } finally { 22 | if (resource != null) resource.close() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/scala/com/ridemission/rest/HttpConstants.scala: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2010 Mission Motors, Inc. 3 | * Kindly released under the Apache Source License (http://www.apache.org/licenses/LICENSE-2.0.html) on Feb 19th, 2013 4 | */ 5 | package com.ridemission.rest 6 | 7 | import scala.util.matching._ 8 | import scala.io._ 9 | import scala.collection.mutable.ListBuffer 10 | 11 | import java.io._ 12 | import java.net._ 13 | import java.util.concurrent._ 14 | 15 | import com.geeksville.util._ 16 | import com.geeksville.util.ThreadTools._ 17 | import Using._ 18 | 19 | object HttpConstants { 20 | val utf = "; charset=utf-8" 21 | 22 | val contentTypeText = "text/plain" + utf 23 | val contentTypeHtml = "text/html" + utf 24 | val contentTypeJson = "text/json" + utf 25 | val contentTypeBinary = "application/octet-stream" 26 | 27 | val extensionToMime = Map( 28 | "html" -> contentTypeHtml, 29 | "txt" -> contentTypeText, 30 | "png" -> "image/png", 31 | "js" -> ("application/javascript" + utf), 32 | "ttf" -> "font/truetype", 33 | "otf" -> "font/opentype", 34 | "css" -> ("text/css" + utf), 35 | "xml" -> ("application/xml" + utf), 36 | "xpi" -> "application/x-xpinstall") 37 | } 38 | 39 | object Method extends Enumeration { 40 | type Method = Value 41 | 42 | val GET = Value("GET") 43 | val POST = Value("POST") 44 | val PUT = Value("PUT") 45 | } -------------------------------------------------------------------------------- /common/src/main/webapp/.gitignore: -------------------------------------------------------------------------------- 1 | README.html 2 | checklist.html 3 | -------------------------------------------------------------------------------- /common/src/main/webapp/build-coffee.sh: -------------------------------------------------------------------------------- 1 | coffee -o js/ -cw coffee/ 2 | -------------------------------------------------------------------------------- /common/src/main/webapp/build.sh: -------------------------------------------------------------------------------- 1 | echo building coffeescripts 2 | coffee -o js/ coffee/ 3 | echo building checklist 4 | haml checklist/plane.haml checklist/plane.html 5 | haml checklist/copter.haml checklist/copter.html 6 | echo building README 7 | haml README.haml README.html 8 | 9 | -------------------------------------------------------------------------------- /common/src/main/webapp/checklist/.gitignore: -------------------------------------------------------------------------------- 1 | copter.html 2 | plane.html 3 | -------------------------------------------------------------------------------- /common/src/main/webapp/checklist/copter.haml: -------------------------------------------------------------------------------- 1 | plane.haml -------------------------------------------------------------------------------- /common/src/main/webapp/coffee/test-takeoff.coffee: -------------------------------------------------------------------------------- 1 | 2 | v = GCSAPI.vehicle 3 | v.set_mode('LOITER') 4 | v.arm() 5 | alt = 10 6 | v.goto_guided(v.location[0], v.location[1], v.location[2] + alt) -------------------------------------------------------------------------------- /common/src/main/webapp/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/src/main/webapp/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /common/src/main/webapp/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/src/main/webapp/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /common/src/main/webapp/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geeksville/arduleader/15f8c543ddead9a5a272fd891545325aff8ef7d7/common/src/main/webapp/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /common/src/main/webapp/gcsapi-README.md: -------------------------------------------------------------------------------- 1 | # GCSAPI 2 | 3 | The GCSAPI is specified in GCSAPI.coffee (and implicitly GCSAPI.js). However 4 | we'll eventually grow this into a user manual on how to script APM ground 5 | control stations. 6 | 7 | ## Checklists 8 | 9 | Currently the main usage of GCSAPI is for checklists. If you would like to 10 | customize the checklists (and preferably contribute your improvements) you 11 | probably want to edit plane.html or copter.html. Those files use some shared 12 | javascript that lives in checklist.js. 13 | 14 | ## Examples 15 | 16 | Example javascript code that uses the API: 17 | 18 | ### Getting vehicle location: 19 | ```js 20 | var loc = GCSAPI.vehicle.location() 21 | ``` 22 | 23 | ### Plopping down a view that shows red or green based on vehicle mode (from checklist.coffee/js): 24 | ```js 25 | new GCSAPI.View.VehicleBased( 26 | el: '#manual-mode' 27 | watching: 'manual_mode' 28 | getContent: () -> 29 | mode = this.model.current_mode() 30 | msg = if (mode == "MANUAL") || (mode == "STABILIZE") 31 | alertSuccess('Vehicle in MANUAL mode') 32 | else 33 | alertFail('Vehicle not in MANUAL mode') 34 | ) 35 | ``` -------------------------------------------------------------------------------- /common/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | hello-backbonejs 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /common/src/main/webapp/js/.gitignore: -------------------------------------------------------------------------------- 1 | gcsapi.js 2 | gcstest.js -------------------------------------------------------------------------------- /common/src/main/webapp/js/test-takeoff.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.3 2 | (function() { 3 | var alt, v; 4 | 5 | v = GCSAPI.vehicle; 6 | 7 | v.set_mode('LOITER'); 8 | 9 | v.arm(); 10 | 11 | alt = 10; 12 | 13 | v.goto_guided(v.location[0], v.location[1], v.location[2] + alt); 14 | 15 | }).call(this); 16 | -------------------------------------------------------------------------------- /common/src/main/webapp/test-takeoff-aio.gcs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Auto Takeoff 6 | 7 | 8 |

Auto takeoff

9 |

Welcome to the bleeding edge

10 |

11 | Congratulations (or apologies). By running this script you 12 | just launched your copter and told it to hover 10m above the 13 | launch location. 14 |

15 | 16 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /common/src/main/webapp/test-takeoff.gcs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Auto Takeoff 6 | 7 | 8 |

Auto takeoff

9 |

Welcome to the bleeding edge

10 |

11 | Congratulations (or apologies). By running this script you 12 | just launched your copter and told it to enter follow me mode. 13 |

14 | 15 | 16 |