├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── arrays.xml
│ │ │ │ ├── styles.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── attr.xml
│ │ │ ├── layout
│ │ │ │ ├── fragment_can_variables.xml
│ │ │ │ ├── fragment_gps_satellites.xml
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── fragment_can_data.xml
│ │ │ │ ├── template_flow_master_detail.xml
│ │ │ │ ├── fragment_gps_sentences.xml
│ │ │ │ ├── fragment_device_list.xml
│ │ │ │ ├── rule_list.xml
│ │ │ │ ├── dialog_text.xml
│ │ │ │ ├── action_property.xml
│ │ │ │ ├── rule_list_content.xml
│ │ │ │ ├── template_activity_master_detail.xml
│ │ │ │ ├── activity_usb_status.xml
│ │ │ │ ├── listitem_carduino_variable.xml
│ │ │ │ ├── action_detail.xml
│ │ │ │ ├── listitem_app_statistic.xml
│ │ │ │ ├── overlay_bubble_car.xml
│ │ │ │ └── rule_detail.xml
│ │ │ ├── drawable
│ │ │ │ ├── selector_bottom_navigation.xml
│ │ │ │ ├── ic_menu_add.xml
│ │ │ │ ├── ic_menu_ok.xml
│ │ │ │ ├── ic_dashboard_stats_rules.xml
│ │ │ │ ├── ic_cc_mode_face.xml
│ │ │ │ ├── ic_cc_mode_ws.xml
│ │ │ │ ├── ic_cc_mode_feet.xml
│ │ │ │ ├── ic_action_device_disconnect.xml
│ │ │ │ ├── ic_device_feature_events.xml
│ │ │ │ ├── ic_cc_status_small_off.xml
│ │ │ │ ├── ic_cc_status_small_on.xml
│ │ │ │ ├── ic_overlay_close.xml
│ │ │ │ ├── ic_pref_rules.xml
│ │ │ │ ├── ic_dashboard_stats_vars.xml
│ │ │ │ ├── ic_dashboard_stats_feature.xml
│ │ │ │ ├── ic_tab_gps_raw.xml
│ │ │ │ ├── ic_action_device_reset.xml
│ │ │ │ ├── ic_action_device_reboot.xml
│ │ │ │ ├── ic_pref_compatibility.xml
│ │ │ │ ├── ic_pref_overlay.xml
│ │ │ │ ├── ic_cc_fan.xml
│ │ │ │ ├── ic_device_feature_location.xml
│ │ │ │ ├── ic_cc_off.xml
│ │ │ │ ├── ic_device_feature_errors.xml
│ │ │ │ ├── ic_pref_gps.xml
│ │ │ │ ├── ic_cc_recirculation.xml
│ │ │ │ ├── ic_cc_status_off.xml
│ │ │ │ ├── ic_cc_status_on.xml
│ │ │ │ ├── seekarc_thumb.xml
│ │ │ │ ├── ic_pref_devices.xml
│ │ │ │ ├── ic_action_device_delete.xml
│ │ │ │ ├── ic_cc_ac.xml
│ │ │ │ ├── ic_dashboard_stats_devices.xml
│ │ │ │ ├── ic_banner_permissions.xml
│ │ │ │ ├── ic_device_type_unknown.xml
│ │ │ │ ├── ic_device_feature_unknown.xml
│ │ │ │ ├── ic_device_type_gps.xml
│ │ │ │ ├── ic_tab_usb.xml
│ │ │ │ ├── ic_pref_usb.xml
│ │ │ │ ├── ic_tab_gps_status.xml
│ │ │ │ ├── ic_pref_car.xml
│ │ │ │ ├── ic_tab_car.xml
│ │ │ │ ├── ic_device_feature_can.xml
│ │ │ │ ├── ic_device_type_carduino.xml
│ │ │ │ ├── ic_cc_mode_bg.xml
│ │ │ │ ├── ic_cc_auto.xml
│ │ │ │ ├── ic_dashboard_settings.xml
│ │ │ │ ├── bg_dashboard_toolbar.xml
│ │ │ │ ├── bg_dashboard_menu.xml
│ │ │ │ ├── ic_cc_rwh.xml
│ │ │ │ └── ic_cc_wsh.xml
│ │ │ ├── menu
│ │ │ │ ├── action_detail_menu.xml
│ │ │ │ ├── rule_detail_menu.xml
│ │ │ │ ├── dashboard_menu.xml
│ │ │ │ ├── bottom_navigation_carduino_monitor.xml
│ │ │ │ ├── bottom_navigation_gps_monitor.xml
│ │ │ │ └── dashboard_actions.xml
│ │ │ ├── xml
│ │ │ │ ├── pref_compatibility.xml
│ │ │ │ └── pref_main.xml
│ │ │ └── layout-w900dp
│ │ │ │ └── template_flow_master_detail.xml
│ │ └── java
│ │ │ └── de
│ │ │ └── jlab
│ │ │ └── cardroid
│ │ │ ├── devices
│ │ │ ├── serial
│ │ │ │ ├── SerialConnectionListener.java
│ │ │ │ ├── carduino
│ │ │ │ │ ├── EventInteractable.java
│ │ │ │ │ ├── EventObservable.java
│ │ │ │ │ ├── CarduinoEventInteractable.java
│ │ │ │ │ ├── CarduinoPacketParser.java
│ │ │ │ │ ├── CarduinoMetaType.java
│ │ │ │ │ ├── CarduinoEventType.java
│ │ │ │ │ ├── CarduinoFeatureDetector.java
│ │ │ │ │ ├── CarduinoEventParser.java
│ │ │ │ │ ├── CarduinoErrorParser.java
│ │ │ │ │ ├── CarduinoPacketType.java
│ │ │ │ │ └── CarduinoCanParser.java
│ │ │ │ ├── SerialPacket.java
│ │ │ │ ├── gps
│ │ │ │ │ ├── GpsSatellite.java
│ │ │ │ │ ├── GpsSerialReader.java
│ │ │ │ │ └── GpsPositionParser.java
│ │ │ │ ├── BinarySerialPacket.java
│ │ │ │ └── SerialReader.java
│ │ │ ├── Feature.java
│ │ │ ├── ObservableFeature.java
│ │ │ ├── usb
│ │ │ │ ├── UsbDevice.java
│ │ │ │ └── serial
│ │ │ │ │ ├── gps
│ │ │ │ │ └── GpsUsbDevice.java
│ │ │ │ │ └── carduino
│ │ │ │ │ ├── KeepAlive.java
│ │ │ │ │ └── CarduinoCanInteractable.java
│ │ │ ├── ui
│ │ │ │ ├── DeviceListViewModel.java
│ │ │ │ └── DeviceDetailViewModel.java
│ │ │ ├── storage
│ │ │ │ ├── DeviceConverters.java
│ │ │ │ ├── DeviceDao.java
│ │ │ │ └── DeviceEntity.java
│ │ │ ├── identification
│ │ │ │ ├── DeviceConnectionId.java
│ │ │ │ └── DeviceUid.java
│ │ │ ├── DeviceDisconnectedReceiver.java
│ │ │ ├── DeviceConnectionRequest.java
│ │ │ ├── detection
│ │ │ │ ├── UsbDeviceDetector.java
│ │ │ │ ├── GpsSerialMatcher.java
│ │ │ │ ├── CarduinoSerialMatcher.java
│ │ │ │ └── UsbSerialDeviceDetector.java
│ │ │ ├── DeviceType.java
│ │ │ └── DeviceServiceConnection.java
│ │ │ ├── errors
│ │ │ ├── ErrorObservable.java
│ │ │ ├── Error.java
│ │ │ └── ErrorController.java
│ │ │ ├── car
│ │ │ ├── CanInteractable.java
│ │ │ ├── CanObservable.java
│ │ │ └── ui
│ │ │ │ └── CarMonitorActivity.java
│ │ │ ├── rules
│ │ │ ├── Trigger.java
│ │ │ ├── actions
│ │ │ │ ├── AudioAction.java
│ │ │ │ ├── VoiceAction.java
│ │ │ │ ├── KillAppAction.java
│ │ │ │ ├── StartAppAction.java
│ │ │ │ ├── WifiToggleAction.java
│ │ │ │ └── MediaKeyAction.java
│ │ │ ├── storage
│ │ │ │ ├── RuleDefinition.java
│ │ │ │ ├── EventViewListModel.java
│ │ │ │ ├── EventViewDetailModel.java
│ │ │ │ ├── ActionDao.java
│ │ │ │ ├── ActionViewDetailModel.java
│ │ │ │ ├── EventDao.java
│ │ │ │ ├── ActionEntity.java
│ │ │ │ ├── EventEntity.java
│ │ │ │ ├── ActionPropertyConverters.java
│ │ │ │ ├── EventRepository.java
│ │ │ │ └── ActionRepository.java
│ │ │ ├── properties
│ │ │ │ ├── Property.java
│ │ │ │ ├── ActionPropertyEditor.java
│ │ │ │ └── PropertyValue.java
│ │ │ ├── KnownEvents.java
│ │ │ ├── FragmentActionListener.java
│ │ │ ├── Rule.java
│ │ │ ├── Event.java
│ │ │ └── ActionDefinition.java
│ │ │ ├── gps
│ │ │ ├── GpsObservable.java
│ │ │ └── ui
│ │ │ │ └── GpsMonitorActivity.java
│ │ │ ├── utils
│ │ │ ├── StopWatch.java
│ │ │ ├── permissions
│ │ │ │ ├── StandardPermission.java
│ │ │ │ ├── OverlayPermission.java
│ │ │ │ ├── PermissionRequest.java
│ │ │ │ └── MockLocationPermission.java
│ │ │ ├── ui
│ │ │ │ ├── UnitValues.java
│ │ │ │ ├── RoundCardView.java
│ │ │ │ ├── DialogUtils.java
│ │ │ │ └── FeatureActivity
│ │ │ │ │ └── StatusGridAdapter.java
│ │ │ ├── MultiMap.java
│ │ │ └── UsageStatistics.java
│ │ │ ├── overlay
│ │ │ ├── SeekArcEvent.java
│ │ │ ├── AbstractOverlayController.java
│ │ │ └── OverlayToggleButton.java
│ │ │ ├── variables
│ │ │ ├── ObservableValue.java
│ │ │ ├── ObservableValueBag.java
│ │ │ ├── ScriptEngine.java
│ │ │ └── Expression.java
│ │ │ └── storage
│ │ │ └── CardroidDatabase.java
│ ├── test
│ │ └── java
│ │ │ └── de
│ │ │ └── jlab
│ │ │ └── cardroid
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── de
│ │ └── jlab
│ │ └── cardroid
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── runConfigurations.xml
└── gradle.xml
├── gradle.properties
└── CHANGELOG.md
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rampage128/cardroid/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/SerialConnectionListener.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial;
2 |
3 | public interface SerialConnectionListener {
4 | void onConnect();
5 | void onDisconnect();
6 | }
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 25 16:57:20 CEST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 200dp
5 | 300dp
6 | 16dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/Feature.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices;
2 |
3 | public interface Feature {
4 |
5 | enum State {
6 | AVAILABLE,
7 | UNAVAILABLE
8 | }
9 |
10 | void setDevice(Device device);
11 | Device getDevice();
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_can_variables.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/EventInteractable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import de.jlab.cardroid.devices.Feature;
4 |
5 | public interface EventInteractable extends Feature {
6 |
7 | void sendEvent(byte eventId, byte[] payload);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_bottom_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_gps_satellites.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_add.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_ok.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/SerialPacket.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | public interface SerialPacket {
9 |
10 | void serialize(@NonNull ByteArrayOutputStream stream) throws IOException;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_stats_rules.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_mode_face.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_mode_ws.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_mode_feet.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_device_disconnect.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_feature_events.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_status_small_off.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_status_small_on.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/errors/ErrorObservable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.errors;
2 |
3 | import de.jlab.cardroid.devices.ObservableFeature;
4 |
5 | public interface ErrorObservable extends ObservableFeature {
6 |
7 | interface ErrorListener extends ObservableFeature.Listener {
8 | void onError(int errorNumber);
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_overlay_close.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_stats_vars.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/car/CanInteractable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.car;
2 |
3 | import de.jlab.cardroid.devices.Feature;
4 |
5 | public interface CanInteractable extends Feature {
6 | void registerCanId(CanPacketDescriptor descriptor);
7 | void unregisterCanId(CanPacketDescriptor descriptor);
8 | void sendPacket(int canId, byte[] data);
9 |
10 | void startSniffer();
11 | void stopSniffer();
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_stats_feature.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tab_gps_raw.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/action_detail_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_device_reset.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/rule_detail_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/car/CanObservable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.car;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import de.jlab.cardroid.devices.ObservableFeature;
6 |
7 | public interface CanObservable extends ObservableFeature {
8 |
9 | interface CanPacketListener extends ObservableFeature.Listener {
10 | void onReceive(@NonNull CanPacket packet);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/Trigger.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | public final class Trigger {
4 |
5 | private Event event;
6 |
7 | public Trigger(Event event) {
8 | this.event = event;
9 | }
10 |
11 | public Event getEvent() {
12 | return this.event;
13 | }
14 |
15 | public boolean triggers(Event otherEvent) {
16 | return this.event.equals(otherEvent);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/AudioAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.content.Context;
4 | import android.media.AudioManager;
5 |
6 | import de.jlab.cardroid.rules.Action;
7 |
8 | abstract class AudioAction extends Action {
9 |
10 | protected AudioManager getAudioManager(Context context) {
11 | return (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_device_reboot.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/RuleDefinition.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.List;
4 |
5 | import androidx.room.Embedded;
6 | import androidx.room.Relation;
7 |
8 | public class RuleDefinition {
9 |
10 | @Embedded
11 | public EventEntity event;
12 |
13 | @Relation(parentColumn = "uid", entityColumn = "event_uid", entity = ActionEntity.class)
14 | public List actions;
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/dashboard_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_compatibility.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_overlay.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/properties/Property.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.properties;
2 |
3 | public class Property {
4 | private T value;
5 | private String key;
6 |
7 | public Property(String key, T value) {
8 | this.key = key;
9 | this.value = value;
10 | }
11 |
12 | public T getValue() {
13 | return this.value;
14 | }
15 |
16 | public String getKey() {
17 | return this.key;
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_fan.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_feature_location.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_off.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_feature_errors.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_can_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/de/jlab/cardroid/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/template_flow_master_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_gps.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/ObservableFeature.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | public interface ObservableFeature extends Feature {
7 |
8 | void addListener(@NonNull LT listener);
9 | void removeListener(@NonNull LT listener);
10 |
11 | void setDevice(@NonNull Device device);
12 | @Nullable
13 | Device getDevice();
14 |
15 | interface Listener {}
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_recirculation.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/EventObservable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import androidx.annotation.NonNull;
4 | import de.jlab.cardroid.devices.ObservableFeature;
5 | import de.jlab.cardroid.devices.identification.DeviceUid;
6 |
7 | public interface EventObservable extends ObservableFeature {
8 |
9 | interface EventListener extends ObservableFeature.Listener {
10 | void onEvent(int eventNum, @NonNull DeviceUid deviceUid);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_status_off.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_status_on.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/seekarc_thumb.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
8 |
11 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - 115200
5 | - 4800
6 | - 9600
7 |
8 |
9 |
10 | - 4
11 | - 5
12 | - 6
13 | - 7
14 | - 8
15 | - 9
16 | - 10
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_devices.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_action_device_delete.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/gps/GpsObservable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.gps;
2 |
3 | import de.jlab.cardroid.devices.ObservableFeature;
4 | import de.jlab.cardroid.devices.serial.gps.GpsPosition;
5 |
6 | public interface GpsObservable extends ObservableFeature {
7 |
8 | interface PositionListener extends ObservableFeature.Listener {
9 | // TODO: Remove sentence from callback. That is serial shit that has to go somewhere else later
10 | void onUpdate(GpsPosition position, String sentence);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_ac.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_stats_devices.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/KnownEvents.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import de.jlab.cardroid.rules.storage.EventEntity;
7 |
8 | public final class KnownEvents {
9 |
10 | private Map eventMap = new HashMap<>();
11 |
12 | public void addEvent(Event event) {
13 | this.eventMap.put(event.getDescriptor(), event);
14 | }
15 |
16 | public Event getEvent(EventEntity descriptor) {
17 | return this.eventMap.get(descriptor);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_gps_sentences.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_banner_permissions.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_type_unknown.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_feature_unknown.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_type_gps.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_device_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/usb/UsbDevice.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.usb;
2 |
3 | import android.app.Application;
4 |
5 | import androidx.annotation.NonNull;
6 | import de.jlab.cardroid.devices.Device;
7 | import de.jlab.cardroid.devices.identification.DeviceConnectionId;
8 |
9 | public abstract class UsbDevice extends Device {
10 |
11 | private android.hardware.usb.UsbDevice device;
12 |
13 | public UsbDevice(@NonNull android.hardware.usb.UsbDevice device, @NonNull Application app) {
14 | super(app);
15 | this.device = device;
16 | this.setConnectionId(DeviceConnectionId.fromUsbDevice(device));
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tab_usb.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_usb.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tab_gps_status.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_navigation_carduino_monitor.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_navigation_gps_monitor.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/EventViewListModel.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import android.app.Application;
4 |
5 | import java.util.List;
6 |
7 | import androidx.lifecycle.AndroidViewModel;
8 | import androidx.lifecycle.LiveData;
9 |
10 | public class EventViewListModel extends AndroidViewModel {
11 |
12 | private LiveData> allEvents;
13 |
14 | public EventViewListModel(Application application) {
15 | super(application);
16 | EventRepository repository = new EventRepository(application);
17 | this.allEvents = repository.getAll();
18 | }
19 |
20 | public LiveData> getAll() { return this.allEvents; }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_pref_car.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_tab_car.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/FragmentActionListener.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | import de.jlab.cardroid.rules.storage.ActionEntity;
4 | import de.jlab.cardroid.rules.storage.EventEntity;
5 | import de.jlab.cardroid.rules.storage.RuleDefinition;
6 |
7 | public interface FragmentActionListener {
8 |
9 | int COMMAND_ADD = 0;
10 | int COMMAND_EDIT = 1;
11 | int COMMAND_SAVE = 2;
12 | int COMMAND_CANCEL = 3;
13 | int COMMAND_DELETE = 4;
14 | int COMMAND_UPDATED = 5;
15 |
16 | void onEventChange(int command, EventEntity eventEntity);
17 |
18 | void onActionChange(int command, ActionEntity actionEntity);
19 |
20 | void onRuleChange(int command, RuleDefinition ruleDefinition);
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/EventViewDetailModel.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import android.app.Application;
4 |
5 | import androidx.lifecycle.AndroidViewModel;
6 | import androidx.lifecycle.LiveData;
7 |
8 | public class EventViewDetailModel extends AndroidViewModel {
9 |
10 | private EventRepository repository;
11 |
12 | public EventViewDetailModel(Application application) {
13 | super(application);
14 | repository = new EventRepository(application);
15 | }
16 |
17 | public LiveData getAsRule(int eventUid) { return repository.getAsRule(eventUid); }
18 |
19 | public void updateEvent(EventEntity eventEntity) { this.repository.update(eventEntity); }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_feature_can.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_device_type_carduino.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/ActionDao.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.List;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.room.Dao;
7 | import androidx.room.Delete;
8 | import androidx.room.Insert;
9 | import androidx.room.Query;
10 | import androidx.room.Update;
11 |
12 | @Dao
13 | public interface ActionDao {
14 |
15 | @Query("SELECT * FROM actions")
16 | List getAll();
17 |
18 | @Query("SELECT * FROM actions WHERE uid =:uid")
19 | LiveData get(int uid);
20 |
21 | @Insert
22 | void insert(ActionEntity... actionEntities);
23 |
24 | @Update
25 | void update(ActionEntity... actionEntities);
26 |
27 | @Delete()
28 | void delete(ActionEntity... actionEntities);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoEventInteractable.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import de.jlab.cardroid.devices.Device;
4 | import de.jlab.cardroid.devices.usb.serial.carduino.CarduinoUsbDevice;
5 |
6 | public final class CarduinoEventInteractable implements EventInteractable {
7 |
8 | private CarduinoUsbDevice device;
9 |
10 | @Override
11 | public void sendEvent(byte eventId, byte[] payload) {
12 | this.device.send(CarduinoPacketType.createPacket(CarduinoPacketType.EVENT, eventId, payload));
13 | }
14 |
15 | @Override
16 | public void setDevice(Device device) {
17 | this.device = (CarduinoUsbDevice)device;
18 | }
19 |
20 | @Override
21 | public Device getDevice() {
22 | return this.device;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoPacketParser.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import androidx.annotation.NonNull;
4 | import de.jlab.cardroid.devices.serial.SerialReader;
5 |
6 | public abstract class CarduinoPacketParser implements SerialReader.SerialPacketListener {
7 |
8 | @Override
9 | public final void onReceivePackets(@NonNull CarduinoSerialPacket[] packets) {
10 | for (CarduinoSerialPacket packet : packets) {
11 | if (this.shouldHandlePacket(packet)) {
12 | this.handlePacket(packet);
13 | }
14 | }
15 | }
16 |
17 | protected abstract boolean shouldHandlePacket(@NonNull CarduinoSerialPacket packet);
18 | protected abstract void handlePacket(@NonNull CarduinoSerialPacket packet);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/ui/DeviceListViewModel.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.ui;
2 |
3 | import android.app.Application;
4 |
5 | import java.util.List;
6 |
7 | import androidx.lifecycle.AndroidViewModel;
8 | import androidx.lifecycle.LiveData;
9 | import de.jlab.cardroid.devices.storage.DeviceEntity;
10 | import de.jlab.cardroid.devices.storage.DeviceRepository;
11 |
12 | public final class DeviceListViewModel extends AndroidViewModel {
13 |
14 | private LiveData> devices;
15 |
16 | public DeviceListViewModel(Application application) {
17 | super(application);
18 | DeviceRepository repository = new DeviceRepository(application);
19 | this.devices = repository.getAll();
20 | }
21 |
22 | public LiveData> getAll() { return this.devices; }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/pref_compatibility.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 | android.useAndroidX=true
14 | android.enableJetifier=true
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_mode_bg.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/ActionViewDetailModel.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import android.app.Application;
4 |
5 | import androidx.lifecycle.AndroidViewModel;
6 | import androidx.lifecycle.LiveData;
7 |
8 | public class ActionViewDetailModel extends AndroidViewModel {
9 |
10 | private ActionRepository repository;
11 |
12 | public ActionViewDetailModel(Application application) {
13 | super(application);
14 | repository = new ActionRepository(application);
15 | }
16 |
17 | public LiveData get(int uid) { return repository.get(uid); }
18 |
19 | public void insert(ActionEntity actionEntity) {
20 | this.repository.insert(actionEntity);
21 | }
22 |
23 | public void update(ActionEntity actionEntity) {
24 | this.repository.update(actionEntity);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_auto.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/VoiceAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.speech.RecognizerIntent;
6 |
7 | import java.util.HashMap;
8 |
9 | import de.jlab.cardroid.rules.Action;
10 | import de.jlab.cardroid.rules.properties.ActionPropertyEditor;
11 |
12 | public final class VoiceAction extends Action {
13 |
14 | @Override
15 | public void execute(Context context) {
16 | Intent voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE);
17 | voiceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
18 | context.startActivity(voiceIntent);
19 | }
20 |
21 | @Override
22 | protected void setKnownProperties(HashMap knownProperties) {
23 | // Intentionally left blank
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/de/jlab/cardroid/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid;
2 |
3 | import android.content.Context;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 |
8 | import androidx.test.InstrumentationRegistry;
9 | import androidx.test.runner.AndroidJUnit4;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumentation test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() throws Exception {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getTargetContext();
24 |
25 | assertEquals("de.jlab.cardroid", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/Rule.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Collections;
7 |
8 | import androidx.annotation.NonNull;
9 |
10 | public final class Rule {
11 |
12 | private Trigger trigger;
13 | private ArrayList actions = new ArrayList<>();
14 |
15 | public Rule(Trigger trigger, Action... actions) {
16 | this.trigger = trigger;
17 | Collections.addAll(this.actions, actions);
18 | }
19 |
20 | public Trigger getTrigger() {
21 | return this.trigger;
22 | }
23 |
24 | public void trigger(@NonNull Event event, @NonNull Context context) {
25 | if (this.trigger.triggers(event)) {
26 | for (Action action : this.actions) {
27 | action.execute(context);
28 | }
29 | }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/StopWatch.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public final class StopWatch {
6 |
7 | private static final long NANOS_TO_MILLIS = 1000000;
8 |
9 | public enum Unit {
10 | NANOS(1),
11 | MILLIS(NANOS_TO_MILLIS),
12 | SECONDS(NANOS_TO_MILLIS * 1000);
13 |
14 | private long conversion;
15 |
16 | Unit(long conversion) {
17 | this.conversion = conversion;
18 | }
19 |
20 | public long convert(long nanos) {
21 | return nanos / this.conversion;
22 | }
23 | }
24 |
25 | private long start = 0;
26 |
27 | public void start() {
28 | this.start = System.nanoTime();
29 | }
30 |
31 | public long take(@NonNull Unit unit) {
32 | return unit.convert(System.nanoTime() - this.start);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/errors/Error.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.errors;
2 |
3 | public final class Error {
4 | private int errorNumber;
5 | private long lastOccurence;
6 | private int count;
7 |
8 | public Error(int errorNumber) {
9 | this.errorNumber = errorNumber;
10 | }
11 |
12 | public void count(int errorNumber) {
13 | if (this.errorNumber == errorNumber) {
14 | this.lastOccurence = System.currentTimeMillis();
15 | this.count++;
16 | }
17 | }
18 |
19 | public long getLastOccurence() {
20 | return lastOccurence;
21 | }
22 |
23 | public int getCount() {
24 | return this.count;
25 | }
26 |
27 | public int getErrorNumber() {
28 | return this.errorNumber;
29 | }
30 |
31 | public String getErrorCode() {
32 | return String.format("%02X", this.errorNumber);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rule_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_settings.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/ui/DeviceDetailViewModel.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.ui;
2 |
3 | import android.app.Application;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.lifecycle.AndroidViewModel;
7 | import androidx.lifecycle.LiveData;
8 | import de.jlab.cardroid.devices.storage.DeviceEntity;
9 | import de.jlab.cardroid.devices.storage.DeviceRepository;
10 |
11 | public final class DeviceDetailViewModel extends AndroidViewModel {
12 |
13 | private DeviceRepository repository;
14 |
15 | public DeviceDetailViewModel(@NonNull Application application) {
16 | super(application);
17 | this.repository = new DeviceRepository(application);
18 |
19 | }
20 |
21 | public LiveData getDeviceEntity(int entityId) {
22 | return this.repository.get(entityId);
23 | }
24 |
25 | public void update(DeviceEntity entity) {
26 | this.repository.update(entity);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/properties/ActionPropertyEditor.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.properties;
2 |
3 | import android.content.Context;
4 |
5 | public interface ActionPropertyEditor {
6 |
7 | void show(Property currentValue, Context context, PropertyListener listener);
8 | PropertyValue getDefaultValue();
9 |
10 | String getPropertyLabel(Property> property, Context context);
11 |
12 | /*
13 | public Class getType() {
14 | ParameterizedType parameterizedType = (ParameterizedType)getClass().getGenericSuperclass();
15 | Objects.requireNonNull(parameterizedType, "ActionPropertyEditor must explicitly define its generic type");
16 | @SuppressWarnings("unchecked")
17 | Class type = (Class) parameterizedType.getActualTypeArguments()[0];
18 |
19 | return type;
20 | }
21 | */
22 |
23 | interface PropertyListener {
24 | void onItemSelected(PropertyValue item);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoMetaType.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | public enum CarduinoMetaType {
7 | CONNECTION_REQUEST(0x00),
8 | START_SNIFFING(0x0a),
9 | STOP_SNIFFING(0x0b),
10 | SET_UID(0x49),
11 | CAR_DATA_DEFINITION(0x63),
12 | BAUD_RATE_REQUEST(0x72);
13 |
14 | private byte command;
15 |
16 | CarduinoMetaType(int command) {
17 | this.command = (byte)command;
18 | }
19 |
20 | public boolean equals(byte type) {
21 | return this.command == type;
22 | }
23 |
24 | public byte getType() {
25 | return this.command;
26 | }
27 |
28 | public static CarduinoSerialPacket createPacket(@NonNull CarduinoMetaType event, @Nullable byte[] payload) {
29 | return CarduinoPacketType.createPacket(CarduinoPacketType.META, event.command, payload);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/storage/DeviceConverters.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.storage;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Arrays;
7 |
8 | import androidx.room.TypeConverter;
9 | import de.jlab.cardroid.devices.identification.DeviceUid;
10 |
11 | public final class DeviceConverters {
12 |
13 | @TypeConverter
14 | public static ArrayList readFeatures(String value) {
15 | return new ArrayList<>(Arrays.asList(TextUtils.split(value, ",")));
16 | }
17 |
18 | @TypeConverter
19 | public static String writeFeatures(ArrayList list) {
20 | return TextUtils.join(",", list);
21 | }
22 |
23 | @TypeConverter
24 | public static DeviceUid readDeviceUid(String value) {
25 | return new DeviceUid(value);
26 | }
27 |
28 | @TypeConverter
29 | public static String writeDeviceUid(DeviceUid uid) {
30 | return uid.toString();
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\tools\development\android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/permissions/StandardPermission.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils.permissions;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.StringRes;
8 | import androidx.core.app.ActivityCompat;
9 | import androidx.core.content.PermissionChecker;
10 |
11 | public final class StandardPermission extends Permission {
12 |
13 | public StandardPermission(@NonNull String permissionKey, @NonNull Constraint constraint, @StringRes int info) {
14 | super(permissionKey, constraint, info);
15 | }
16 |
17 | @Override
18 | public boolean isGranted(@NonNull Context context) {
19 | return PermissionChecker.checkSelfPermission(context, this.getPermissionKey()) == PermissionChecker.PERMISSION_GRANTED;
20 | }
21 |
22 | @Override
23 | public void request(@NonNull Activity activity) {
24 | ActivityCompat.requestPermissions(activity, new String[] { this.getPermissionKey() }, 1337);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-w900dp/template_flow_master_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/gps/GpsSatellite.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.gps;
2 |
3 | public final class GpsSatellite {
4 |
5 | private int prn = 0;
6 | private float elevation = 0;
7 | private float azimuth = 0;
8 | private int snr = 0;
9 |
10 | private long lastUpdate = 0;
11 |
12 | public GpsSatellite(int prn) {
13 | this.prn = prn;
14 | }
15 |
16 | public int getPrn() {
17 | return prn;
18 | }
19 |
20 | public float getElevation() {
21 | return elevation;
22 | }
23 |
24 | public float getAzimuth() {
25 | return azimuth;
26 | }
27 |
28 | public int getSnr() {
29 | return snr;
30 | }
31 |
32 | public long getLastUpdate() {
33 | return this.lastUpdate;
34 | }
35 |
36 | public void update(float elevation, float azimuth, int snr) {
37 | this.elevation = elevation;
38 | this.azimuth = azimuth;
39 | this.snr = snr;
40 | this.lastUpdate = System.currentTimeMillis();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/storage/DeviceDao.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.storage;
2 |
3 | import java.util.List;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.room.Dao;
7 | import androidx.room.Delete;
8 | import androidx.room.Insert;
9 | import androidx.room.Query;
10 | import androidx.room.Update;
11 |
12 | @Dao
13 | public interface DeviceDao {
14 |
15 | @Query("SELECT * FROM devices ORDER BY display_name ASC")
16 | List getAllSynchronous();
17 |
18 | @Query("SELECT * FROM devices ORDER BY display_name ASC")
19 | LiveData> getAll();
20 |
21 | @Query("SELECT * FROM devices WHERE uid = :uid")
22 | LiveData get(int uid);
23 |
24 | @Query("SELECT * FROM devices WHERE device_uid = :deviceUid")
25 | List getSynchronous(String deviceUid);
26 |
27 | @Insert
28 | void insert(DeviceEntity... deviceEntities);
29 |
30 | @Update
31 | void update(DeviceEntity... deviceEntities);
32 |
33 | @Delete()
34 | void delete(DeviceEntity... deviceEntities);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/EventDao.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.List;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.room.Dao;
7 | import androidx.room.Insert;
8 | import androidx.room.OnConflictStrategy;
9 | import androidx.room.Query;
10 | import androidx.room.Transaction;
11 | import androidx.room.Update;
12 |
13 | @Dao
14 | public interface EventDao {
15 |
16 | @Query("SELECT * FROM events")
17 | LiveData> getAll();
18 |
19 | @Query("SELECT * FROM events WHERE identifier =:identifier")
20 | LiveData get(int identifier);
21 |
22 | @Transaction
23 | @Query("SELECT * FROM events")
24 | LiveData> getAllRules();
25 |
26 | @Transaction
27 | @Query("SELECT * FROM events WHERE uid =:eventUid")
28 | LiveData getAsRule(int eventUid);
29 |
30 | @Insert(onConflict = OnConflictStrategy.IGNORE)
31 | void insert(EventEntity... eventEntities);
32 |
33 | @Update
34 | void update(EventEntity... eventEntities);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_dashboard_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
7 |
8 |
9 |
10 |
11 | -
16 |
18 |
22 |
23 |
24 | -
30 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/KillAppAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.app.ActivityManager;
4 | import android.content.Context;
5 |
6 | import java.util.HashMap;
7 |
8 | import de.jlab.cardroid.rules.Action;
9 | import de.jlab.cardroid.rules.properties.ActionPropertyEditor;
10 | import de.jlab.cardroid.rules.properties.AppSelectionPropertyEditor;
11 |
12 | public final class KillAppAction extends Action {
13 |
14 | private static final String PREFIX = "action_killapp";
15 |
16 | private static final String PROPERTY_PACKAGE = PREFIX + "_package";
17 |
18 | @Override
19 | public void execute(Context context) {
20 | ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
21 | am.restartPackage(PROPERTY_PACKAGE);
22 | am.killBackgroundProcesses((String)getPropertyValue(PROPERTY_PACKAGE));
23 | }
24 |
25 | @Override
26 | protected void setKnownProperties(HashMap knownProperties) {
27 | knownProperties.put(PROPERTY_PACKAGE, new AppSelectionPropertyEditor());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/gps/GpsSerialReader.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.gps;
2 |
3 | import java.util.ArrayList;
4 |
5 | import androidx.annotation.NonNull;
6 | import de.jlab.cardroid.devices.serial.SerialReader;
7 |
8 | public final class GpsSerialReader extends SerialReader {
9 |
10 | private StringBuilder dataLine = new StringBuilder();
11 |
12 | @Override
13 | protected GpsSerialPacket[] createPackets(@NonNull byte[] data) {
14 | ArrayList packets = new ArrayList<>();
15 | for (byte dataByte : data) {
16 | if (dataByte == 0x0D || dataByte == 0x0A) {
17 | continue;
18 | } else if (dataByte == 0x24) {
19 | String rawData = this.dataLine.toString();
20 | if (rawData.startsWith("$")) {
21 | packets.add(new GpsSerialPacket(this.dataLine.toString()));
22 | }
23 | this.dataLine.setLength(0);
24 | }
25 | this.dataLine.append((char) dataByte);
26 | }
27 | return packets.toArray(new GpsSerialPacket[0]);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/overlay/SeekArcEvent.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.overlay;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public final class SeekArcEvent {
6 |
7 | public enum Type {
8 | TRACKING_STARTED,
9 | TRACKING_STOPPED,
10 | PROGRESS_CHANGED
11 | }
12 |
13 | private SeekArc seekArc;
14 | private Type type = Type.TRACKING_STARTED;
15 | private int progress = 0;
16 | private boolean isUserEvent = false;
17 |
18 | public SeekArcEvent(@NonNull SeekArc seekArc) {
19 | this.seekArc = seekArc;
20 | }
21 |
22 | public void update(int progress, boolean isUserEvent, @NonNull Type type) {
23 | this.progress = progress;
24 | this.isUserEvent = isUserEvent;
25 | this.type = type;
26 | }
27 |
28 | public int getProgress() {
29 | return this.progress;
30 | }
31 |
32 | @NonNull
33 | public SeekArc getSeekArc() {
34 | return this.seekArc;
35 | }
36 |
37 | public boolean isUserEvent() {
38 | return this.isUserEvent;
39 | }
40 |
41 | @NonNull
42 | public Type getType() {
43 | return this.type;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/Event.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.Objects;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import de.jlab.cardroid.R;
10 | import de.jlab.cardroid.rules.storage.EventEntity;
11 |
12 | public final class Event {
13 |
14 | private EventEntity descriptor;
15 |
16 | public Event(EventEntity descriptor) {
17 | this.descriptor = descriptor;
18 | }
19 |
20 | public EventEntity getDescriptor() {
21 | return this.descriptor;
22 | }
23 |
24 | public static String getLocalizedNameFromIdentifier(int identifier, @NonNull Context context) {
25 | int resId = context.getResources().getIdentifier("event_" + identifier, "string", context.getPackageName());
26 | if (resId > 0) {
27 | return context.getResources().getString(resId);
28 | }
29 | return context.getResources().getString(R.string.event_unknown, identifier);
30 | }
31 |
32 | public boolean equals(@Nullable Event other) {
33 | return other != null && Objects.equals(this.descriptor, other.descriptor);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_dashboard_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
7 |
8 |
9 |
10 |
11 | -
16 |
18 |
24 |
25 |
26 | -
32 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/StartAppAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 |
6 | import java.util.HashMap;
7 |
8 | import de.jlab.cardroid.rules.Action;
9 | import de.jlab.cardroid.rules.properties.ActionPropertyEditor;
10 | import de.jlab.cardroid.rules.properties.AppSelectionPropertyEditor;
11 |
12 | public final class StartAppAction extends Action {
13 |
14 | private static final String PREFIX = "action_startapp";
15 |
16 | private static final String PROPERTY_PACKAGE = PREFIX + "_package";
17 |
18 | @Override
19 | public void execute(Context context) {
20 | Intent intent = context.getPackageManager().getLaunchIntentForPackage((String)getPropertyValue(PROPERTY_PACKAGE));
21 | if (intent != null) {
22 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
23 | context.startActivity(intent);
24 | }
25 | // TODO handle case of uninstalled app
26 | }
27 |
28 | @Override
29 | protected void setKnownProperties(HashMap knownProperties) {
30 | knownProperties.put(PROPERTY_PACKAGE, new AppSelectionPropertyEditor());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoEventType.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | /**
7 | * @Deprecated Hardcoded event types are part of the LegacyDevice. The possible events should
8 | * be broadcasted by the device on handshake and then made available as an option in the user
9 | * interface when designing custom screens.
10 | */
11 | @Deprecated
12 | public enum CarduinoEventType {
13 | CC_OFF_BUTTON(0x01),
14 | CC_AC_BUTTON(0x02),
15 | CC_AUTO_BUTTON(0x03),
16 | CC_RECIRCULATION_BUTTON(0x04),
17 | CC_WSH_BUTTON(0x05),
18 | CC_RWH_BUTTON(0x06),
19 | CC_MODE_BUTTON(0x07),
20 | CC_TEMPERATURE(0x08),
21 | CC_FAN_LEVEL(0x09);
22 |
23 | private byte command;
24 |
25 | CarduinoEventType(int command) {
26 | this.command = (byte)command;
27 | }
28 |
29 | public byte getCommand() {
30 | return this.command;
31 | }
32 |
33 | public static CarduinoSerialPacket createPacket(@NonNull CarduinoEventType event, @Nullable byte[] payload) {
34 | return CarduinoPacketType.createPacket(CarduinoPacketType.EVENT, event.command, payload);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/identification/DeviceConnectionId.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.identification;
2 |
3 | import android.bluetooth.BluetoothDevice;
4 | import android.hardware.usb.UsbDevice;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 |
9 | public final class DeviceConnectionId {
10 |
11 | private String connectionId;
12 |
13 | private DeviceConnectionId(String connectionId) {
14 | this.connectionId = connectionId;
15 | }
16 |
17 | public static DeviceConnectionId fromUsbDevice(@NonNull UsbDevice device) {
18 | return new DeviceConnectionId(device.getDeviceName());
19 | }
20 |
21 | public static DeviceConnectionId fromBluetoothDevice(@NonNull BluetoothDevice device) {
22 | return new DeviceConnectionId(device.getAddress());
23 | }
24 |
25 | public boolean equals(@Nullable DeviceConnectionId other) {
26 | return other != null && this.connectionId.equals(other.connectionId);
27 | }
28 |
29 | @Override
30 | public int hashCode() {
31 | return this.connectionId.hashCode();
32 | }
33 |
34 | @NonNull
35 | @Override
36 | public String toString() {
37 | return this.connectionId;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/ActionDefinition.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | public class ActionDefinition {
8 | private Class extends Action> actionType = null;
9 | private String label = null;
10 |
11 | public ActionDefinition(@NonNull Class extends Action> actionType, Context context) {
12 | this.actionType = actionType;
13 | this.label = getLocalizedNameFromClassName(actionType.getSimpleName(), context);
14 | }
15 |
16 | public Class extends Action> getActionType() {
17 | return this.actionType;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return this.label;
23 | }
24 |
25 | public static String getLocalizedNameFromClassName(@NonNull String className, Context context) {
26 | String identifier = className.substring(className.lastIndexOf('.') + 1).replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
27 | int resId = context.getResources().getIdentifier(identifier, "string", context.getPackageName());
28 | if (resId > 0) {
29 | return context.getResources().getString(resId);
30 | }
31 | return identifier;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/ui/UnitValues.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils.ui;
2 |
3 | import android.content.Context;
4 | import android.text.Html;
5 | import android.text.Spanned;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.StringRes;
9 | import de.jlab.cardroid.R;
10 |
11 | public final class UnitValues {
12 |
13 | public static Spanned getFancyDecimalValue(float value) {
14 | String[] parts = Float.toString(value).split("\\.");
15 | String decimals = parts.length > 1 ? "." + parts[1] + "" : "";
16 | return Html.fromHtml(parts[0] + decimals);
17 | }
18 |
19 | public static int constrainToRange(int value, int min, int max) {
20 | return Math.max(min, Math.min(value, max));
21 | }
22 |
23 | public static float constrainToRange(float value, float min, float max) {
24 | return Math.max(min, Math.min(value, max));
25 | }
26 |
27 | public static String getStatisticString(int count, int average, @StringRes int unit, @NonNull Context context) {
28 | return context.getString(
29 | R.string.status_statistics_value,
30 | count,
31 | context.getString(unit),
32 | average
33 | );
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/properties/PropertyValue.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.properties;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.Objects;
6 |
7 | import androidx.annotation.NonNull;
8 |
9 | public class PropertyValue {
10 | private T value;
11 | private String name;
12 |
13 | public PropertyValue(T value, String name) {
14 | this.value = value;
15 | this.name = name;
16 | }
17 |
18 | public T getValue() {
19 | return this.value;
20 | }
21 |
22 | public String getName() {
23 | return this.name;
24 | }
25 |
26 | public String getLabel(Context context) {
27 | String key = this.name.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
28 | int resId = context.getResources().getIdentifier(key, "string", context.getPackageName());
29 | if (resId > 0) {
30 | return context.getResources().getString(resId);
31 | }
32 | return key;
33 | }
34 |
35 | @NonNull
36 | @Override
37 | public String toString() {
38 | return this.value.toString();
39 | }
40 |
41 | public boolean equals(@NonNull PropertyValue otherValue) {
42 | return Objects.equals(otherValue.value, this.value);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
15 |
16 |
19 |
20 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/variables/ObservableValue.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.variables;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Objects;
5 |
6 | public class ObservableValue {
7 |
8 | private ArrayList observers = new ArrayList<>();
9 | private Object value;
10 |
11 | public ObservableValue(Object value) {
12 | this.value = value;
13 | }
14 |
15 | protected void change(Object value) {
16 | if (!Objects.equals(this.value, value)) {
17 | this.notifyChange(this.value, value);
18 | }
19 | this.value = value;
20 | }
21 |
22 | public Object getValue() {
23 | return this.value;
24 | }
25 |
26 | private void notifyChange(Object oldValue, Object newValue) {
27 | for (int i = 0; i < this.observers.size(); i++) {
28 | this.observers.get(i).onChange(oldValue, newValue);
29 | }
30 | }
31 |
32 | public void addObserver(ValueObserver observer) {
33 | this.observers.add(observer);
34 | }
35 |
36 | public void removeObserver(ValueObserver observer) {
37 | this.observers.remove(observer);
38 | }
39 |
40 |
41 | public interface ValueObserver {
42 | void onChange(Object oldValue, Object newValue);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/BinarySerialPacket.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.IOException;
5 | import java.util.Arrays;
6 |
7 | import androidx.annotation.NonNull;
8 |
9 | public abstract class BinarySerialPacket implements SerialPacket {
10 |
11 | protected byte[] data;
12 |
13 | public BinarySerialPacket(@NonNull byte[] rawData) {
14 | this.data = rawData;
15 | }
16 |
17 | @Override
18 | public void serialize(@NonNull ByteArrayOutputStream stream) throws IOException {
19 | stream.write(this.data);
20 | }
21 |
22 | protected int readByte(int index) {
23 | return this.data[index] & 0xFF;
24 | }
25 |
26 | protected long readDWord(int index) {
27 | long value = 0;
28 | for (int i = index; i < index + 4; i++) {
29 | value = (value << 8) + (this.data[i] & 0xff);
30 | }
31 | return value;
32 | }
33 |
34 | protected byte[] readBytes(int startIndex, int length) {
35 | return Arrays.copyOfRange(this.data, startIndex, startIndex + length);
36 | }
37 |
38 | protected byte[] readBytes(int startIndex) {
39 | return Arrays.copyOfRange(this.data, startIndex, this.data.length);
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoFeatureDetector.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import android.util.Log;
4 |
5 | import java.util.ArrayList;
6 |
7 | import de.jlab.cardroid.devices.usb.serial.carduino.CarduinoUsbDevice;
8 |
9 | public final class CarduinoFeatureDetector extends CarduinoPacketParser {
10 |
11 | private ArrayList knownPacketTypes = new ArrayList<>();
12 | private CarduinoUsbDevice device;
13 |
14 | public CarduinoFeatureDetector(CarduinoUsbDevice device) {
15 | this.device = device;
16 | }
17 |
18 | @Override
19 | protected boolean shouldHandlePacket(CarduinoSerialPacket packet) {
20 | return !this.knownPacketTypes.contains(packet.getPacketType());
21 | }
22 |
23 | @Override
24 | protected void handlePacket(CarduinoSerialPacket packet) {
25 | byte rawPacketType = packet.getPacketType();
26 | this.knownPacketTypes.add(rawPacketType);
27 | CarduinoPacketType type = CarduinoPacketType.getFromPacket(packet);
28 | if (type != null) {
29 | this.device.addDynamicFeature(type);
30 | } else {
31 | Log.e(this.getClass().getSimpleName(), "Device registered unknown feature: " + new String(new byte[] { rawPacketType }));
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/WifiToggleAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.content.Context;
4 | import android.net.wifi.WifiManager;
5 |
6 | import java.util.HashMap;
7 |
8 | import de.jlab.cardroid.rules.Action;
9 | import de.jlab.cardroid.rules.properties.ActionPropertyEditor;
10 | import de.jlab.cardroid.rules.properties.OptionPropertyEditor;
11 | import de.jlab.cardroid.rules.properties.PropertyValue;
12 |
13 | public final class WifiToggleAction extends Action {
14 |
15 | private static final String PREFIX = "action_wifitoggle";
16 |
17 | private static final String PROPERTY_STATE = PREFIX + "_state";
18 |
19 | @Override
20 | public void execute(Context context) {
21 | WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
22 | wifi.setWifiEnabled((Boolean)this.getPropertyValue(PROPERTY_STATE));
23 | }
24 |
25 | @Override
26 | protected void setKnownProperties(HashMap knownProperties) {
27 | knownProperties.put(PROPERTY_STATE, new OptionPropertyEditor(new PropertyValue[] {
28 | new PropertyValue<>(true, PREFIX + "_on"),
29 | new PropertyValue<>(false, PREFIX + "_off")
30 | }, 0));
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/permissions/OverlayPermission.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils.permissions;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.os.Build;
8 | import android.provider.Settings;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | public final class OverlayPermission extends Permission {
13 |
14 | public static final String PERMISSION_KEY = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
15 |
16 | public OverlayPermission(@NonNull Constraint constraint, int usage) {
17 | super(PERMISSION_KEY, constraint, usage);
18 | }
19 |
20 | @Override
21 | public boolean isGranted(@NonNull Context context) {
22 | return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);
23 | }
24 |
25 | @Override
26 | public void request(@NonNull Activity activity) {
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
28 | // Open screen to grant overlay permission
29 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
30 | Uri.parse("package:" + activity.getPackageName()));
31 | activity.startActivityForResult(intent, 0);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/ui/RoundCardView.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils.ui;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import com.google.android.material.card.MaterialCardView;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.annotation.Nullable;
10 |
11 | public final class RoundCardView extends MaterialCardView {
12 |
13 | private int measuredCornerRadius = 0;
14 |
15 | public RoundCardView(@NonNull Context context) {
16 | super(context);
17 | }
18 |
19 | public RoundCardView(@NonNull Context context, @Nullable AttributeSet attrs) {
20 | super(context, attrs);
21 | }
22 |
23 | public RoundCardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
24 | super(context, attrs, defStyleAttr);
25 | }
26 |
27 | @Override
28 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
29 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
30 |
31 | int newMeasuredCornerRadius = Math.min(this.getMeasuredWidth(), this.getMeasuredHeight());
32 | if (newMeasuredCornerRadius != this.measuredCornerRadius) {
33 | this.measuredCornerRadius = newMeasuredCornerRadius;
34 | this.setRadius(newMeasuredCornerRadius / 2f);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/DeviceDisconnectedReceiver.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.hardware.usb.UsbDevice;
7 | import android.hardware.usb.UsbManager;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 |
11 | public final class DeviceDisconnectedReceiver extends BroadcastReceiver {
12 | @Override
13 | public void onReceive(Context context, Intent intent) {
14 | String action = intent.getAction();
15 | Bundle bundle = intent.getExtras();
16 | if (bundle != null) {
17 | UsbDevice device = bundle.getParcelable(UsbManager.EXTRA_DEVICE);
18 |
19 | if (device != null && UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
20 | disconnectDevice(device, context);
21 | }
22 | }
23 | }
24 |
25 | private void disconnectDevice(UsbDevice device, Context context) {
26 | Intent intent = new Intent(context.getApplicationContext(), DeviceConnectionActivity.class);
27 | intent.putExtra(UsbManager.EXTRA_DEVICE, device);
28 | intent.setAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
29 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
30 | context.getApplicationContext().startActivity(intent);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/dashboard_actions.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/action_property.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/rule_list_content.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/template_activity_master_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/DeviceConnectionRequest.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import de.jlab.cardroid.devices.identification.DeviceUid;
6 |
7 | public final class DeviceConnectionRequest {
8 |
9 | private Long waitingSince;
10 | private DeviceUid predictedDeviceUid;
11 | private Device device;
12 |
13 | public DeviceConnectionRequest(@NonNull Device device, @Nullable DeviceUid predictedDeviceUid) {
14 | this.device = device;
15 | this.predictedDeviceUid = predictedDeviceUid;
16 | this.waitingSince = System.nanoTime();
17 | }
18 |
19 | public boolean hasIdentity() {
20 | return this.predictedDeviceUid != null;
21 | }
22 |
23 | public boolean shouldYieldFor(@NonNull Device otherDevice) {
24 | return this.predictedDeviceUid != null &&
25 | this.device.getClass().equals(otherDevice.getClass()) &&
26 | otherDevice.isDevice(this.predictedDeviceUid);
27 | }
28 |
29 | public boolean hasTimedOut(long timeout) {
30 | return System.nanoTime() - waitingSince > timeout * 1000000;
31 | }
32 |
33 | @NonNull
34 | public Device getDevice() {
35 | return this.device;
36 | }
37 |
38 | @NonNull
39 | @Override
40 | public String toString() {
41 | return "!" + this.predictedDeviceUid + "@" + this.device.getConnectionId();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoEventParser.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import java.util.ArrayList;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import de.jlab.cardroid.devices.Device;
8 |
9 | public final class CarduinoEventParser extends CarduinoPacketParser implements EventObservable {
10 |
11 | private Device device;
12 | private ArrayList listeners = new ArrayList<>();
13 |
14 | @Override
15 | protected boolean shouldHandlePacket(@NonNull CarduinoSerialPacket packet) {
16 | return CarduinoPacketType.EVENT.equals(packet.getPacketType());
17 | }
18 |
19 | @Override
20 | protected void handlePacket(@NonNull CarduinoSerialPacket packet) {
21 | for (int i = 0; i < this.listeners.size(); i++) {
22 | this.listeners.get(i).onEvent(packet.getPacketId(), this.device.getDeviceUid());
23 | }
24 | }
25 |
26 | @Override
27 | public void addListener(@NonNull EventListener listener) {
28 | this.listeners.add(listener);
29 | }
30 |
31 | @Override
32 | public void removeListener(@NonNull EventListener listener) {
33 | this.listeners.remove(listener);
34 | }
35 |
36 | @Override
37 | public void setDevice(@NonNull Device device) {
38 | this.device = device;
39 | }
40 |
41 | @Nullable
42 | @Override
43 | public Device getDevice() {
44 | return this.device;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/usb/serial/gps/GpsUsbDevice.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.usb.serial.gps;
2 |
3 | import android.app.Application;
4 | import android.hardware.usb.UsbDevice;
5 |
6 | import androidx.annotation.NonNull;
7 | import de.jlab.cardroid.devices.identification.DeviceUid;
8 | import de.jlab.cardroid.devices.serial.gps.GpsPositionParser;
9 | import de.jlab.cardroid.devices.serial.gps.GpsSerialReader;
10 | import de.jlab.cardroid.devices.usb.serial.UsbSerialDevice;
11 |
12 | public final class GpsUsbDevice extends UsbSerialDevice {
13 |
14 | private GpsPositionParser positionParser = new GpsPositionParser();
15 | private DeviceUid uid;
16 |
17 | public GpsUsbDevice(@NonNull UsbDevice device, int defaultBaudrate, @NonNull Application app) {
18 | super(device, defaultBaudrate, app);
19 |
20 | this.uid = DeviceUid.fromUsbDevice(device);
21 | }
22 |
23 | @Override
24 | protected GpsSerialReader onOpenSuccess() {
25 | GpsSerialReader reader = new GpsSerialReader();
26 | reader.addSerialPacketListener(this.positionParser);
27 | this.setDeviceUid(this.uid);
28 | this.setState(State.READY);
29 | this.addFeature(this.positionParser);
30 | return reader;
31 | }
32 |
33 | @Override
34 | protected void onOpenFailed() {}
35 |
36 | @Override
37 | protected void onClose(GpsSerialReader reader) {
38 | reader.removeSerialPacketListener(this.positionParser);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/storage/CardroidDatabase.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.storage;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.room.Room;
6 | import androidx.room.RoomDatabase;
7 | import de.jlab.cardroid.devices.storage.DeviceDao;
8 | import de.jlab.cardroid.devices.storage.DeviceEntity;
9 | import de.jlab.cardroid.rules.storage.ActionDao;
10 | import de.jlab.cardroid.rules.storage.ActionEntity;
11 | import de.jlab.cardroid.rules.storage.EventDao;
12 | import de.jlab.cardroid.rules.storage.EventEntity;
13 |
14 | @androidx.room.Database(entities = { ActionEntity.class, EventEntity.class, DeviceEntity.class }, version = 3, exportSchema = false)
15 | public abstract class CardroidDatabase extends RoomDatabase {
16 | public abstract ActionDao actionDao();
17 | public abstract EventDao eventDao();
18 | public abstract DeviceDao deviceDao();
19 |
20 | private static volatile CardroidDatabase INSTANCE;
21 |
22 | public static CardroidDatabase getDatabase(final Context context) {
23 | if (INSTANCE == null) {
24 | synchronized (CardroidDatabase.class) {
25 | if (INSTANCE == null) {
26 | INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
27 | CardroidDatabase.class, "cardroid")
28 | .fallbackToDestructiveMigrationFrom(1, 2)
29 | .build();
30 | }
31 | }
32 | }
33 | return INSTANCE;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/usb/serial/carduino/KeepAlive.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.usb.serial.carduino;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 |
6 | import androidx.annotation.NonNull;
7 | import de.jlab.cardroid.devices.Device;
8 | import de.jlab.cardroid.devices.usb.serial.UsbSerialDevice;
9 |
10 | public final class KeepAlive {
11 |
12 | private long timeout;
13 | private long interval;
14 | private UsbSerialDevice device;
15 | private byte[] keepAliveData;
16 |
17 | private Handler handler;
18 | private Runnable runner = this::send;
19 |
20 | public KeepAlive(long timeout, long interval, @NonNull byte[] keepAliveData, @NonNull UsbSerialDevice device, @NonNull Context context) {
21 | this.timeout = timeout;
22 | this.interval = interval;
23 | this.device = device;
24 | this.keepAliveData = keepAliveData;
25 | this.handler = new Handler(context.getMainLooper());
26 | }
27 |
28 | public void start() {
29 | this.run(this.timeout);
30 | }
31 |
32 | public void stop() {
33 | this.handler.removeCallbacks(runner);
34 | }
35 |
36 | private void run(long delay) {
37 | this.stop();
38 | if (this.device.getState() != Device.State.INVALID) {
39 | this.handler.postDelayed(runner, delay);
40 | }
41 | }
42 |
43 | private void send() {
44 | this.device.send(this.keepAliveData);
45 | this.run(this.interval);
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/detection/UsbDeviceDetector.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.detection;
2 |
3 | import android.hardware.usb.UsbDevice;
4 |
5 | import androidx.annotation.NonNull;
6 | import de.jlab.cardroid.devices.DeviceConnectionRequest;
7 | import de.jlab.cardroid.devices.DeviceService;
8 |
9 | public abstract class UsbDeviceDetector {
10 |
11 | private DeviceSink sink;
12 | private DeviceDrain drain;
13 |
14 | public void setSink(@NonNull DeviceSink sink) {
15 | this.sink = sink;
16 | }
17 |
18 | public void setOnError(@NonNull DeviceDrain drain) {
19 | this.drain = drain;
20 | }
21 |
22 | public void identify(@NonNull UsbDevice device, @NonNull DeviceService service) {
23 | if (!this.startIdentification(device, service)) {
24 | this.detectionFailed(device);
25 | }
26 | }
27 |
28 | protected void deviceDetected(@NonNull DeviceConnectionRequest connectionRequest) {
29 | this.sink.deviceDetected(connectionRequest);
30 | }
31 |
32 | protected void detectionFailed(@NonNull UsbDevice device) {
33 | this.drain.deviceDetectionFailed(device);
34 | }
35 |
36 | protected abstract boolean startIdentification(@NonNull UsbDevice device, @NonNull DeviceService service);
37 |
38 | public interface DeviceSink {
39 | void deviceDetected(@NonNull DeviceConnectionRequest connectionRequest);
40 | }
41 |
42 | public interface DeviceDrain {
43 | void deviceDetectionFailed(@NonNull UsbDevice device);
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/variables/ObservableValueBag.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.variables;
2 |
3 | import java.util.HashMap;
4 |
5 | public final class ObservableValueBag {
6 |
7 | private HashMap variables = new HashMap<>();
8 |
9 | public void put(String name, ObservableValue value) {
10 | this.variables.put(name, value);
11 | }
12 |
13 | public ObservableValue get(String name) {
14 | return this.variables.get(name);
15 | }
16 |
17 | public ObservableValueBag allFromExpression(String expression) {
18 | ObservableValueBag bag = new ObservableValueBag();
19 | for (String name : this.variables.keySet()) {
20 | if (expression.contains(name)) {
21 | bag.put(name, this.variables.get(name));
22 | }
23 | }
24 | return bag;
25 | }
26 |
27 | public String[] getNames() {
28 | return this.variables.keySet().toArray(new String[0]);
29 | }
30 |
31 | public static BagBuilder build() {
32 | return new BagBuilder();
33 | }
34 |
35 | public static class BagBuilder {
36 | private ObservableValueBag bag;
37 |
38 | private BagBuilder() {
39 | this.bag = new ObservableValueBag();
40 | }
41 |
42 | public BagBuilder addVariable(String name, ObservableValue value) {
43 | this.bag.put(name, value);
44 | return this;
45 | }
46 |
47 | public ObservableValueBag get() {
48 | return this.bag;
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #607D8B
6 | #cd000000
7 | #EEEEEE
8 | #ffffffff
9 | #99ffffff
10 | #1e000000
11 |
12 | #8A000000
13 | #424242
14 | #2E7D32
15 | #00838F
16 | #1565C0
17 | #5E35B1
18 |
19 | #99AAAAAA
20 |
21 | #99AAAAAA
22 | #ffEEDC82
23 | #55D456
24 |
25 | #FFFFBE00
26 | #44EEEEEE
27 | #424242
28 |
29 | #FFD8D8D8
30 | #FF383838
31 |
32 | #F44336
33 | #FF9800
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/pref_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
20 |
21 |
25 |
26 |
31 |
32 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoErrorParser.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import java.util.ArrayList;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import de.jlab.cardroid.devices.Device;
8 | import de.jlab.cardroid.errors.ErrorObservable;
9 |
10 | public final class CarduinoErrorParser extends CarduinoPacketParser implements ErrorObservable {
11 |
12 | private Device device;
13 | private ArrayList errorHandlers = new ArrayList<>();
14 |
15 | @Override
16 | protected boolean shouldHandlePacket(CarduinoSerialPacket packet) {
17 | return CarduinoPacketType.ERROR.equals(packet.getPacketType());
18 | }
19 |
20 | @Override
21 | protected void handlePacket(CarduinoSerialPacket packet) {
22 | int errorNumber = packet.getPacketId();
23 |
24 | for (int i = 0; i < this.errorHandlers.size(); i++) {
25 | this.errorHandlers.get(i).onError(errorNumber);
26 | }
27 | }
28 |
29 | @Override
30 | public void addListener(@NonNull ErrorListener listener) {
31 | this.errorHandlers.add(listener);
32 | }
33 |
34 | @Override
35 | public void removeListener(@NonNull ErrorListener listener) {
36 | this.errorHandlers.remove(listener);
37 | }
38 |
39 | @Override
40 | public void setDevice(@NonNull Device device) {
41 | this.device = device;
42 | }
43 |
44 | @Nullable
45 | @Override
46 | public Device getDevice() {
47 | return this.device;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/ActionEntity.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.List;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.room.ColumnInfo;
7 | import androidx.room.Entity;
8 | import androidx.room.ForeignKey;
9 | import androidx.room.Index;
10 | import androidx.room.PrimaryKey;
11 | import androidx.room.TypeConverters;
12 | import de.jlab.cardroid.rules.properties.Property;
13 |
14 | import static androidx.room.ForeignKey.CASCADE;
15 |
16 | @Entity(tableName = "actions",
17 | foreignKeys = {
18 | @ForeignKey(entity = EventEntity.class, parentColumns = "uid", childColumns = "event_uid", onDelete = CASCADE)
19 | },
20 | indices = {
21 | @Index("event_uid")
22 | })
23 | public class ActionEntity {
24 |
25 | @PrimaryKey(autoGenerate = true)
26 | public int uid;
27 |
28 | @ColumnInfo(name = "class_name")
29 | public String className;
30 |
31 | @ColumnInfo(name = "event_uid")
32 | public int eventUid;
33 |
34 | @TypeConverters(ActionPropertyConverters.class)
35 | public List> properties;
36 |
37 | @NonNull
38 | public Property> getPropertyByKey(@NonNull String key, Object defaultValue) {
39 | if (properties != null && !properties.isEmpty()) {
40 | for (Property> property : this.properties) {
41 | if (key.equals(property.getKey())) {
42 | return property;
43 | }
44 | }
45 | }
46 |
47 | return new Property<>(key, defaultValue);
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/variables/ScriptEngine.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.variables;
2 |
3 | import android.util.Log;
4 |
5 | import org.mozilla.javascript.Context;
6 | import org.mozilla.javascript.Scriptable;
7 |
8 | public final class ScriptEngine {
9 |
10 | private Scriptable scope;
11 |
12 | public ScriptEngine() {
13 | this.scope = this.createContext().initStandardObjects();
14 | }
15 |
16 | public Expression createGlobalExpression(String expression, ObservableValueBag variables, String contextName) {
17 | return new Expression(expression, variables, contextName, this.scope, this);
18 | }
19 |
20 | public Expression createExpression(String expression, ObservableValueBag variables, String contextName) {
21 | Scriptable scope = this.createContext().initStandardObjects();
22 | return new Expression(expression, variables, contextName, scope, this);
23 | }
24 |
25 | public Object evaluate(String expression, String contextName, Scriptable scope) {
26 | Context context = this.createContext();
27 | Object result = 0L;
28 | try {
29 | result = context.evaluateString(scope, expression, contextName, 1, null);
30 | } catch (Exception e) {
31 | Log.e(this.getClass().getSimpleName(), "Error evaluating \"" + expression + "\"", e);
32 | } finally {
33 | Context.exit();
34 | }
35 |
36 | return result;
37 | }
38 |
39 | private Context createContext() {
40 | Context context = Context.enter();
41 | context.setOptimizationLevel(-1); // prevent JVM bytecode generation
42 | return context;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/detection/GpsSerialMatcher.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.detection;
2 |
3 | import android.app.Application;
4 | import android.hardware.usb.UsbDevice;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.annotation.Nullable;
8 | import de.jlab.cardroid.devices.DeviceConnectionRequest;
9 | import de.jlab.cardroid.devices.identification.DeviceUid;
10 | import de.jlab.cardroid.devices.usb.serial.gps.GpsUsbDevice;
11 |
12 | public final class GpsSerialMatcher implements UsbSerialDeviceDetector.SerialMatcher {
13 |
14 | private static final String PATTERN = ".*\\$GP...,.*";
15 |
16 | private String received = "";
17 |
18 | @Nullable
19 | @Override
20 | public DeviceConnectionRequest detect(@NonNull byte[] data, @NonNull UsbDevice device, int baudRate, @NonNull Application app) {
21 | this.received += new String(data);
22 | if (this.received.matches(PATTERN)) {
23 | return new DeviceConnectionRequest(
24 | new GpsUsbDevice(device, baudRate, app),
25 | DeviceUid.fromUsbDevice(device)
26 | );
27 | }
28 | return null;
29 | }
30 |
31 | /*
32 | @Nullable
33 | @Override
34 | public Device detect(@NonNull byte[] data, @NonNull UsbDevice device, int baudRate, @NonNull Application app) {
35 |
36 | }
37 |
38 | @NonNull
39 | @Override
40 | public DeviceConnectionRequest predictDeviceUid(@NonNull UsbDevice device) {
41 | return DeviceUid.fromUsbDevice(device);
42 | }
43 | */
44 | @Override
45 | public void clear() {
46 | this.received = "";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/EventEntity.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.Objects;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import androidx.room.ColumnInfo;
8 | import androidx.room.Entity;
9 | import androidx.room.Index;
10 | import androidx.room.PrimaryKey;
11 | import androidx.room.TypeConverters;
12 | import de.jlab.cardroid.devices.identification.DeviceUid;
13 | import de.jlab.cardroid.devices.storage.DeviceConverters;
14 |
15 | @Entity(tableName = "events", indices = {@Index(value = {"identifier", "device_uid"},
16 | unique = true)})
17 | public class EventEntity {
18 |
19 | public EventEntity(int identifier, @NonNull DeviceUid deviceUid, @NonNull String name) {
20 | this.identifier = identifier;
21 | this.deviceUid = deviceUid;
22 | this.name = name;
23 | }
24 |
25 | @PrimaryKey(autoGenerate = true)
26 | public int uid;
27 |
28 | public int identifier;
29 |
30 | @TypeConverters(DeviceConverters.class)
31 | @ColumnInfo(name = "device_uid")
32 | public DeviceUid deviceUid;
33 |
34 | public String name;
35 |
36 | @Override
37 | public boolean equals(@Nullable Object obj) {
38 | return obj == this ||
39 | (obj instanceof EventEntity && this.equals((EventEntity)obj));
40 | }
41 |
42 | public boolean equals(EventEntity other) {
43 | return other != null &&
44 | this.identifier == other.identifier &&
45 | Objects.equals(this.deviceUid, other.deviceUid);
46 | }
47 |
48 | @Override
49 | public int hashCode() {
50 | return Objects.hash(this.deviceUid) * 31 + ((Integer)this.identifier).hashCode();
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_rwh.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cc_wsh.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_usb_status.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/car/ui/CarMonitorActivity.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.car.ui;
2 |
3 | import android.preference.PreferenceManager;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import de.jlab.cardroid.R;
8 | import de.jlab.cardroid.car.CanObservable;
9 | import de.jlab.cardroid.devices.DeviceService;
10 | import de.jlab.cardroid.devices.DeviceServiceConnection;
11 | import de.jlab.cardroid.devices.Feature;
12 | import de.jlab.cardroid.devices.identification.DeviceUid;
13 | import de.jlab.cardroid.utils.ui.FeatureActivity.FeatureActivity;
14 |
15 | public class CarMonitorActivity extends FeatureActivity {
16 |
17 | @Nullable
18 | @Override
19 | protected DeviceUid getDefaultDeviceUid() {
20 | String deviceUid = PreferenceManager.getDefaultSharedPreferences(this).getString("car_device_uid", null);
21 | return deviceUid != null ? new DeviceUid(deviceUid) : null;
22 | }
23 |
24 | @NonNull
25 | @Override
26 | protected Class extends Feature> getFeatureType() {
27 | return CanObservable.class;
28 | }
29 |
30 | @Override
31 | protected void onDeviceServiceStateChange(@NonNull DeviceService.DeviceServiceBinder deviceService, @NonNull DeviceServiceConnection.Action action) {
32 |
33 | }
34 |
35 | @Override
36 | protected void onDataItemClicked(int id, @Nullable String value) {
37 |
38 | }
39 |
40 | @Override
41 | protected void initContentViews(@NonNull ContentViewConsumer consumer) {
42 | consumer.addContentView(R.id.action_status, new CanVariableFragment());
43 | consumer.addContentView(R.id.action_connection, new CanDataFragment());
44 | }
45 |
46 | @Override
47 | protected int getMenuId() {
48 | return R.menu.bottom_navigation_carduino_monitor;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/gps/ui/GpsMonitorActivity.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.gps.ui;
2 |
3 | import android.preference.PreferenceManager;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.annotation.Nullable;
7 | import de.jlab.cardroid.R;
8 | import de.jlab.cardroid.devices.DeviceService;
9 | import de.jlab.cardroid.devices.DeviceServiceConnection;
10 | import de.jlab.cardroid.devices.Feature;
11 | import de.jlab.cardroid.devices.identification.DeviceUid;
12 | import de.jlab.cardroid.gps.GpsObservable;
13 | import de.jlab.cardroid.utils.ui.FeatureActivity.FeatureActivity;
14 |
15 | public final class GpsMonitorActivity extends FeatureActivity {
16 |
17 | @Nullable
18 | @Override
19 | protected DeviceUid getDefaultDeviceUid() {
20 | String deviceUid = PreferenceManager.getDefaultSharedPreferences(this).getString("gps_device_uid", null);
21 | return deviceUid != null ? new DeviceUid(deviceUid) : null;
22 | }
23 |
24 | @NonNull
25 | @Override
26 | protected Class extends Feature> getFeatureType() {
27 | return GpsObservable.class;
28 | }
29 |
30 | @Override
31 | protected void onDeviceServiceStateChange(@NonNull DeviceService.DeviceServiceBinder deviceService, @NonNull DeviceServiceConnection.Action action) {
32 |
33 | }
34 |
35 | @Override
36 | protected void onDataItemClicked(int id, @Nullable String value) {
37 |
38 | }
39 |
40 | @Override
41 | protected void initContentViews(@NonNull ContentViewConsumer consumer) {
42 | consumer.addContentView(R.id.action_status, new SatelliteFragment());
43 | consumer.addContentView(R.id.action_raw_data, new SentenceFragment());
44 | }
45 |
46 | @Override
47 | protected int getMenuId() {
48 | return R.menu.bottom_navigation_gps_monitor;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/serial/carduino/CarduinoPacketType.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.serial.carduino;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import de.jlab.cardroid.devices.Feature;
6 | import de.jlab.cardroid.devices.usb.serial.carduino.CarduinoCanInteractable;
7 |
8 | public enum CarduinoPacketType {
9 | // FIXME: these should be created on demand. Otherwise multiple Carduino devices will share the same instances of the features
10 | META(0x61),
11 | // TODO: Split CarduinoCanInteractable into CanMessageInteractable and CanFilterInteractable
12 | CAN(0x62, new CarduinoCanParser(), new CarduinoCanInteractable()),
13 | EVENT(0x63, new CarduinoEventParser(), new CarduinoEventInteractable()),
14 | ERROR(0x65, new CarduinoErrorParser());
15 |
16 | private byte type;
17 | private Feature[] features;
18 |
19 | CarduinoPacketType(int type, @Nullable Feature... features) {
20 | this.type = (byte)type;
21 | this.features = features;
22 | }
23 |
24 | public byte getType() {
25 | return this.type;
26 | }
27 |
28 | @Nullable
29 | public Feature[] getFeatures() {
30 | return this.features;
31 | }
32 |
33 | public boolean equals(byte type) {
34 | return this.type == type;
35 | }
36 |
37 | public static CarduinoPacketType getFromPacket(CarduinoSerialPacket packet) {
38 | for (CarduinoPacketType type : CarduinoPacketType.values()) {
39 | if (type.equals(packet.getPacketType())) {
40 | return type;
41 | }
42 | }
43 | return null;
44 | }
45 |
46 | @NonNull
47 | public static CarduinoSerialPacket createPacket(@NonNull CarduinoPacketType type, byte id, @Nullable byte[] payload) {
48 | return CarduinoSerialPacket.create(type.type, id, payload);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/errors/ErrorController.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.errors;
2 |
3 | import android.content.Context;
4 | import android.util.SparseArray;
5 |
6 | import androidx.annotation.NonNull;
7 | import de.jlab.cardroid.devices.Device;
8 | import de.jlab.cardroid.devices.DeviceController;
9 | import de.jlab.cardroid.devices.Feature;
10 |
11 | public final class ErrorController {
12 |
13 | private SparseArray errors = new SparseArray<>();
14 |
15 | private DeviceController deviceController;
16 | private ErrorNotifier errorNotifier;
17 |
18 | private Device.FeatureChangeObserver errorFilter = this::onErrorFeatureChange;
19 | private ErrorObservable.ErrorListener errorListener = this::onError;
20 |
21 |
22 | public ErrorController(@NonNull DeviceController deviceController, @NonNull Context context) {
23 | this.deviceController = deviceController;
24 | this.errorNotifier = new ErrorNotifier(context);
25 | deviceController.subscribeFeature(this.errorFilter, ErrorObservable.class);
26 | }
27 |
28 | public void dispose() {
29 | this.deviceController.unsubscribeFeature(this.errorFilter, ErrorObservable.class);
30 | }
31 |
32 | private void onError(int errorNumber) {
33 | Error error = this.errors.get(errorNumber);
34 | if (error == null) {
35 | error = new Error(errorNumber);
36 | this.errors.put(errorNumber, error);
37 | }
38 | error.count(errorNumber);
39 | this.errorNotifier.onError(error);
40 | }
41 |
42 | private void onErrorFeatureChange(@NonNull ErrorObservable feature, @NonNull Feature.State state) {
43 | if (state == Feature.State.AVAILABLE) {
44 | feature.addListener(this.errorListener);
45 | } else {
46 | feature.removeListener(this.errorListener);
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/devices/detection/CarduinoSerialMatcher.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.devices.detection;
2 |
3 | import android.app.Application;
4 | import android.hardware.usb.UsbDevice;
5 | import android.util.Log;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import de.jlab.cardroid.devices.DeviceConnectionRequest;
10 | import de.jlab.cardroid.devices.serial.carduino.CarduinoPacketType;
11 | import de.jlab.cardroid.devices.serial.carduino.CarduinoSerialPacket;
12 | import de.jlab.cardroid.devices.serial.carduino.CarduinoUidGenerator;
13 | import de.jlab.cardroid.devices.usb.serial.carduino.CarduinoUsbDevice;
14 |
15 | public final class CarduinoSerialMatcher implements UsbSerialDeviceDetector.SerialMatcher {
16 |
17 | private static final String PATTERN = new StringBuilder("[\\S\\s]*")
18 | .append("\\").append((char)CarduinoSerialPacket.HEADER)
19 | .append((char)CarduinoPacketType.META.getType())
20 | .append("[^\\}]*").append("\\").append((char)CarduinoSerialPacket.FOOTER)
21 | .append("[\\S\\s]*").toString();
22 |
23 | private String received = "";
24 |
25 | @Nullable
26 | @Override
27 | public DeviceConnectionRequest detect(@NonNull byte[] data, @NonNull UsbDevice device, int baudRate, @NonNull Application app) {
28 | this.received += new String(data);
29 | Log.e(this.getClass().getSimpleName(), "<- " + this.received + "(" + PATTERN + " = " + this.received.matches(PATTERN) + ")");
30 | if (this.received.matches(PATTERN)) {
31 | return new DeviceConnectionRequest(
32 | new CarduinoUsbDevice(device, baudRate, app),
33 | CarduinoUidGenerator.getUid(this.received)
34 | );
35 | }
36 | return null;
37 | }
38 |
39 | @Override
40 | public void clear() {
41 | this.received = "";
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/actions/MediaKeyAction.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.actions;
2 |
3 | import android.content.Context;
4 | import android.media.AudioManager;
5 | import android.view.KeyEvent;
6 |
7 | import java.util.HashMap;
8 |
9 | import de.jlab.cardroid.rules.properties.ActionPropertyEditor;
10 | import de.jlab.cardroid.rules.properties.OptionPropertyEditor;
11 | import de.jlab.cardroid.rules.properties.PropertyValue;
12 |
13 | public final class MediaKeyAction extends AudioAction {
14 |
15 | private static final String PREFIX = "action_mediakey";
16 |
17 | private static final String PROPERTY_KEY_CODE = PREFIX + "_key_code";
18 |
19 | @Override
20 | public void execute(Context context) {
21 | int keyCode = (Integer)getPropertyValue(PROPERTY_KEY_CODE);
22 | AudioManager audioManager = this.getAudioManager(context);
23 |
24 | if (audioManager != null) {
25 | KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
26 | audioManager.dispatchMediaKeyEvent(downEvent);
27 |
28 | KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
29 | audioManager.dispatchMediaKeyEvent(upEvent);
30 | }
31 | }
32 |
33 | @Override
34 | protected void setKnownProperties(HashMap knownProperties) {
35 | knownProperties.put(PROPERTY_KEY_CODE, new OptionPropertyEditor(new PropertyValue[] {
36 | new PropertyValue<>(KeyEvent.KEYCODE_MEDIA_PLAY, PREFIX + "_play"),
37 | new PropertyValue<>(KeyEvent.KEYCODE_MEDIA_PAUSE, PREFIX + "_pause"),
38 | new PropertyValue<>(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, PREFIX + "_play_pause"),
39 | new PropertyValue<>(KeyEvent.KEYCODE_MEDIA_PREVIOUS, PREFIX + "_previous"),
40 | new PropertyValue<>(KeyEvent.KEYCODE_MEDIA_NEXT, PREFIX + "_next")
41 | }, 2));
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/listitem_carduino_variable.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
20 |
21 |
32 |
33 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/utils/MultiMap.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.utils;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.Set;
6 |
7 | import androidx.annotation.NonNull;
8 |
9 | public final class MultiMap, V> {
10 |
11 | private HashMap> entries = new HashMap<>();
12 |
13 | public void put(@NonNull K key, @NonNull V value) {
14 | ArrayList bucket = this.getOrCreateBucket(key);
15 | if (!bucket.contains(value)) {
16 | bucket.add(value);
17 | }
18 | }
19 |
20 | public ArrayList get(@NonNull K key) {
21 | ArrayList bucket = this.entries.get(key);
22 | if (bucket != null) {
23 | return new ArrayList<>(bucket);
24 | }
25 | return new ArrayList<>();
26 | }
27 |
28 | public ArrayList getAssignable(@NonNull K desiredType) {
29 | ArrayList result = new ArrayList<>();
30 | for (K key : this.entries.keySet()) {
31 | if (key.isAssignableFrom(desiredType)) {
32 | ArrayList localEntries = this.entries.get(key);
33 | if (localEntries != null) {
34 | result.addAll(localEntries);
35 | }
36 | }
37 | }
38 | return result;
39 | }
40 |
41 | public Set keySet() {
42 | return this.entries.keySet();
43 | }
44 |
45 | public void remove(@NonNull K key, @NonNull V value) {
46 | ArrayList bucket = this.entries.get(key);
47 | if (bucket != null) {
48 | bucket.remove(value);
49 | }
50 | }
51 |
52 | public void clear() {
53 | this.entries.clear();
54 | }
55 |
56 | private ArrayList getOrCreateBucket(@NonNull K key) {
57 | ArrayList bucket = this.entries.get(key);
58 | if (bucket == null) {
59 | bucket = new ArrayList<>();
60 | this.entries.put(key, bucket);
61 | }
62 | return bucket;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/app/src/main/java/de/jlab/cardroid/rules/storage/ActionPropertyConverters.java:
--------------------------------------------------------------------------------
1 | package de.jlab.cardroid.rules.storage;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import androidx.arch.core.util.Function;
7 | import androidx.room.TypeConverter;
8 | import de.jlab.cardroid.rules.properties.Property;
9 | import de.jlab.cardroid.utils.storage.ValueConverter;
10 |
11 | public class ActionPropertyConverters {
12 |
13 | private static final ValueConverter, Function> DESERIALIZER = ValueConverter.deserializer();
14 | private static final ValueConverter