getParserForType() {
+ return PARSER;
+ }
+
+ public com.openxc.BinaryMessages.SimpleMessage getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
}
- // @@protoc_insertion_point(class_scope:openxc.SimpleMessage)
}
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_VehicleMessage_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_VehicleMessage_fieldAccessorTable;
+ internal_static_openxc_VehicleMessage_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_VehicleMessage_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_CanMessage_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_CanMessage_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_ControlCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_ControlCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_CanMessage_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_CanMessage_fieldAccessorTable;
+ internal_static_openxc_DiagnosticControlCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_DiagnosticControlCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_ControlCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_ControlCommand_fieldAccessorTable;
+ internal_static_openxc_PassthroughModeControlCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_PassthroughModeControlCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_DiagnosticControlCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_DiagnosticControlCommand_fieldAccessorTable;
+ internal_static_openxc_AcceptanceFilterBypassCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_AcceptanceFilterBypassCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_PassthroughModeControlCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_PassthroughModeControlCommand_fieldAccessorTable;
+ internal_static_openxc_PayloadFormatCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_PayloadFormatCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_AcceptanceFilterBypassCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_AcceptanceFilterBypassCommand_fieldAccessorTable;
+ internal_static_openxc_PredefinedObd2RequestsCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_PredefinedObd2RequestsCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_PayloadFormatCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_PayloadFormatCommand_fieldAccessorTable;
+ internal_static_openxc_NetworkOperatorSettings_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_NetworkOperatorSettings_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_PredefinedObd2RequestsCommand_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_PredefinedObd2RequestsCommand_fieldAccessorTable;
+ internal_static_openxc_NetworkOperatorSettings_NetworkDescriptor_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_NetworkOperatorSettings_NetworkDescriptor_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_CommandResponse_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_CommandResponse_fieldAccessorTable;
+ internal_static_openxc_NetworkDataSettings_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_NetworkDataSettings_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_DiagnosticRequest_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_DiagnosticRequest_fieldAccessorTable;
+ internal_static_openxc_ServerConnectSettings_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_ServerConnectSettings_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_DiagnosticResponse_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_DiagnosticResponse_fieldAccessorTable;
+ internal_static_openxc_ModemConfigurationCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_ModemConfigurationCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_DynamicField_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_DynamicField_fieldAccessorTable;
+ internal_static_openxc_RTCConfigurationCommand_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_RTCConfigurationCommand_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_openxc_SimpleMessage_descriptor;
- private static
- com.google.protobuf.GeneratedMessage.FieldAccessorTable
- internal_static_openxc_SimpleMessage_fieldAccessorTable;
+ internal_static_openxc_CommandResponse_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_CommandResponse_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_DiagnosticRequest_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_DiagnosticRequest_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_DiagnosticResponse_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_DiagnosticResponse_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_DynamicField_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_DynamicField_fieldAccessorTable;
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_openxc_SimpleMessage_descriptor;
+ private static final
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_openxc_SimpleMessage_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
- getDescriptor() {
+ getDescriptor() {
return descriptor;
}
- private static com.google.protobuf.Descriptors.FileDescriptor
- descriptor;
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
static {
java.lang.String[] descriptorData = {
- "\n\014openxc.proto\022\006openxc\"\210\003\n\016VehicleMessag" +
- "e\022)\n\004type\030\001 \001(\0162\033.openxc.VehicleMessage." +
- "Type\022\'\n\013can_message\030\002 \001(\0132\022.openxc.CanMe" +
- "ssage\022-\n\016simple_message\030\003 \001(\0132\025.openxc.S" +
- "impleMessage\0227\n\023diagnostic_response\030\004 \001(" +
- "\0132\032.openxc.DiagnosticResponse\022/\n\017control" +
- "_command\030\005 \001(\0132\026.openxc.ControlCommand\0221" +
- "\n\020command_response\030\006 \001(\0132\027.openxc.Comman" +
- "dResponse\"V\n\004Type\022\007\n\003CAN\020\001\022\n\n\006SIMPLE\020\002\022\016" +
- "\n\nDIAGNOSTIC\020\003\022\023\n\017CONTROL_COMMAND\020\004\022\024\n\020C",
- "OMMAND_RESPONSE\020\005\"\224\001\n\nCanMessage\022\013\n\003bus\030" +
- "\001 \001(\005\022\n\n\002id\030\002 \001(\r\022\014\n\004data\030\003 \001(\014\0224\n\014frame" +
- "_format\030\004 \001(\0162\036.openxc.CanMessage.FrameF" +
- "ormat\")\n\013FrameFormat\022\014\n\010STANDARD\020\001\022\014\n\010EX" +
- "TENDED\020\002\"\270\004\n\016ControlCommand\022)\n\004type\030\001 \001(" +
- "\0162\033.openxc.ControlCommand.Type\022<\n\022diagno" +
- "stic_request\030\002 \001(\0132 .openxc.DiagnosticCo" +
- "ntrolCommand\022G\n\030passthrough_mode_request" +
- "\030\003 \001(\0132%.openxc.PassthroughModeControlCo" +
- "mmand\022O\n acceptance_filter_bypass_comman",
- "d\030\004 \001(\0132%.openxc.AcceptanceFilterBypassC" +
- "ommand\022<\n\026payload_format_command\030\005 \001(\0132\034" +
- ".openxc.PayloadFormatCommand\022O\n predefin" +
- "ed_obd2_requests_command\030\006 \001(\0132%.openxc." +
- "PredefinedObd2RequestsCommand\"\223\001\n\004Type\022\013" +
- "\n\007VERSION\020\001\022\r\n\tDEVICE_ID\020\002\022\016\n\nDIAGNOSTIC" +
- "\020\003\022\017\n\013PASSTHROUGH\020\004\022\034\n\030ACCEPTANCE_FILTER" +
- "_BYPASS\020\005\022\022\n\016PAYLOAD_FORMAT\020\006\022\034\n\030PREDEFI" +
- "NED_OBD2_REQUESTS\020\007\"\236\001\n\030DiagnosticContro" +
- "lCommand\022*\n\007request\030\001 \001(\0132\031.openxc.Diagn",
- "osticRequest\0227\n\006action\030\002 \001(\0162\'.openxc.Di" +
- "agnosticControlCommand.Action\"\035\n\006Action\022" +
- "\007\n\003ADD\020\001\022\n\n\006CANCEL\020\002\"=\n\035PassthroughModeC" +
- "ontrolCommand\022\013\n\003bus\030\001 \001(\005\022\017\n\007enabled\030\002 " +
- "\001(\010\"<\n\035AcceptanceFilterBypassCommand\022\013\n\003" +
- "bus\030\001 \001(\005\022\016\n\006bypass\030\002 \001(\010\"{\n\024PayloadForm" +
- "atCommand\022:\n\006format\030\001 \001(\0162*.openxc.Paylo" +
- "adFormatCommand.PayloadFormat\"\'\n\rPayload" +
- "Format\022\010\n\004JSON\020\001\022\014\n\010PROTOBUF\020\002\"0\n\035Predef" +
- "inedObd2RequestsCommand\022\017\n\007enabled\030\001 \001(\010",
- "\"]\n\017CommandResponse\022)\n\004type\030\001 \001(\0162\033.open" +
- "xc.ControlCommand.Type\022\017\n\007message\030\002 \001(\t\022" +
- "\016\n\006status\030\003 \001(\010\"\375\001\n\021DiagnosticRequest\022\013\n" +
- "\003bus\030\001 \001(\005\022\022\n\nmessage_id\030\002 \001(\r\022\014\n\004mode\030\003" +
- " \001(\r\022\013\n\003pid\030\004 \001(\r\022\017\n\007payload\030\005 \001(\014\022\032\n\022mu" +
- "ltiple_responses\030\006 \001(\010\022\021\n\tfrequency\030\007 \001(" +
- "\001\022\014\n\004name\030\010 \001(\t\022;\n\014decoded_type\030\t \001(\0162%." +
- "openxc.DiagnosticRequest.DecodedType\"!\n\013" +
- "DecodedType\022\010\n\004NONE\020\001\022\010\n\004OBD2\020\002\"\241\001\n\022Diag" +
- "nosticResponse\022\013\n\003bus\030\001 \001(\005\022\022\n\nmessage_i",
- "d\030\002 \001(\r\022\014\n\004mode\030\003 \001(\r\022\013\n\003pid\030\004 \001(\r\022\017\n\007su" +
- "ccess\030\005 \001(\010\022\036\n\026negative_response_code\030\006 " +
- "\001(\r\022\017\n\007payload\030\007 \001(\014\022\r\n\005value\030\010 \001(\001\"\242\001\n\014" +
- "DynamicField\022\'\n\004type\030\001 \001(\0162\031.openxc.Dyna" +
- "micField.Type\022\024\n\014string_value\030\002 \001(\t\022\025\n\rn" +
- "umeric_value\030\003 \001(\001\022\025\n\rboolean_value\030\004 \001(" +
- "\010\"%\n\004Type\022\n\n\006STRING\020\001\022\007\n\003NUM\020\002\022\010\n\004BOOL\020\003" +
- "\"g\n\rSimpleMessage\022\014\n\004name\030\001 \001(\t\022#\n\005value" +
- "\030\002 \001(\0132\024.openxc.DynamicField\022#\n\005event\030\003 " +
- "\001(\0132\024.openxc.DynamicFieldB\034\n\ncom.openxcB",
- "\016BinaryMessages"
+ "\n\014openxc.proto\022\006openxc\"\233\003\n\016VehicleMessag" +
+ "e\022)\n\004type\030\001 \001(\0162\033.openxc.VehicleMessage." +
+ "Type\022\'\n\013can_message\030\002 \001(\0132\022.openxc.CanMe" +
+ "ssage\022-\n\016simple_message\030\003 \001(\0132\025.openxc.S" +
+ "impleMessage\0227\n\023diagnostic_response\030\004 \001(" +
+ "\0132\032.openxc.DiagnosticResponse\022/\n\017control" +
+ "_command\030\005 \001(\0132\026.openxc.ControlCommand\0221" +
+ "\n\020command_response\030\006 \001(\0132\027.openxc.Comman" +
+ "dResponse\022\021\n\ttimestamp\030\007 \001(\004\"V\n\004Type\022\007\n\003" +
+ "CAN\020\001\022\n\n\006SIMPLE\020\002\022\016\n\nDIAGNOSTIC\020\003\022\023\n\017CON" +
+ "TROL_COMMAND\020\004\022\024\n\020COMMAND_RESPONSE\020\005\"\224\001\n" +
+ "\nCanMessage\022\013\n\003bus\030\001 \001(\005\022\n\n\002id\030\002 \001(\r\022\014\n\004" +
+ "data\030\003 \001(\014\0224\n\014frame_format\030\004 \001(\0162\036.openx" +
+ "c.CanMessage.FrameFormat\")\n\013FrameFormat\022" +
+ "\014\n\010STANDARD\020\001\022\014\n\010EXTENDED\020\002\"\227\006\n\016ControlC" +
+ "ommand\022)\n\004type\030\001 \001(\0162\033.openxc.ControlCom" +
+ "mand.Type\022<\n\022diagnostic_request\030\002 \001(\0132 ." +
+ "openxc.DiagnosticControlCommand\022G\n\030passt" +
+ "hrough_mode_request\030\003 \001(\0132%.openxc.Passt" +
+ "hroughModeControlCommand\022O\n acceptance_f" +
+ "ilter_bypass_command\030\004 \001(\0132%.openxc.Acce" +
+ "ptanceFilterBypassCommand\022<\n\026payload_for" +
+ "mat_command\030\005 \001(\0132\034.openxc.PayloadFormat" +
+ "Command\022O\n predefined_obd2_requests_comm" +
+ "and\030\006 \001(\0132%.openxc.PredefinedObd2Request" +
+ "sCommand\022F\n\033modem_configuration_command\030" +
+ "\007 \001(\0132!.openxc.ModemConfigurationCommand" +
+ "\022B\n\031rtc_configuration_command\030\010 \001(\0132\037.op" +
+ "enxc.RTCConfigurationCommand\"\346\001\n\004Type\022\013\n" +
+ "\007VERSION\020\001\022\r\n\tDEVICE_ID\020\002\022\016\n\nDIAGNOSTIC\020" +
+ "\003\022\017\n\013PASSTHROUGH\020\004\022\034\n\030ACCEPTANCE_FILTER_" +
+ "BYPASS\020\005\022\022\n\016PAYLOAD_FORMAT\020\006\022\034\n\030PREDEFIN" +
+ "ED_OBD2_REQUESTS\020\007\022\027\n\023MODEM_CONFIGURATIO" +
+ "N\020\010\022\025\n\021RTC_CONFIGURATION\020\t\022\023\n\017SD_MOUNT_S" +
+ "TATUS\020\n\022\014\n\010PLATFORM\020\013\"\236\001\n\030DiagnosticCont" +
+ "rolCommand\022*\n\007request\030\001 \001(\0132\031.openxc.Dia" +
+ "gnosticRequest\0227\n\006action\030\002 \001(\0162\'.openxc." +
+ "DiagnosticControlCommand.Action\"\035\n\006Actio" +
+ "n\022\007\n\003ADD\020\001\022\n\n\006CANCEL\020\002\"=\n\035PassthroughMod" +
+ "eControlCommand\022\013\n\003bus\030\001 \001(\005\022\017\n\007enabled\030" +
+ "\002 \001(\010\"<\n\035AcceptanceFilterBypassCommand\022\013" +
+ "\n\003bus\030\001 \001(\005\022\016\n\006bypass\030\002 \001(\010\"\214\001\n\024PayloadF" +
+ "ormatCommand\022:\n\006format\030\001 \001(\0162*.openxc.Pa" +
+ "yloadFormatCommand.PayloadFormat\"8\n\rPayl" +
+ "oadFormat\022\010\n\004JSON\020\001\022\014\n\010PROTOBUF\020\002\022\017\n\013MES" +
+ "SAGEPACK\020\003\"0\n\035PredefinedObd2RequestsComm" +
+ "and\022\017\n\007enabled\030\001 \001(\010\"\321\003\n\027NetworkOperator" +
+ "Settings\022\030\n\020allowDataRoaming\030\001 \001(\010\022N\n\022op" +
+ "eratorSelectMode\030\002 \001(\01622.openxc.NetworkO" +
+ "peratorSettings.OperatorSelectMode\022L\n\021ne" +
+ "tworkDescriptor\030\003 \001(\01321.openxc.NetworkOp" +
+ "eratorSettings.NetworkDescriptor\032\230\001\n\021Net" +
+ "workDescriptor\022\014\n\004PLMN\030\001 \001(\r\022R\n\013networkT" +
+ "ype\030\002 \001(\0162=.openxc.NetworkOperatorSettin" +
+ "gs.NetworkDescriptor.NetworkType\"!\n\013Netw" +
+ "orkType\022\007\n\003GSM\020\000\022\t\n\005UTRAN\020\002\"c\n\022OperatorS" +
+ "electMode\022\r\n\tAUTOMATIC\020\000\022\n\n\006MANUAL\020\001\022\016\n\n" +
+ "DEREGISTER\020\002\022\014\n\010SET_ONLY\020\003\022\024\n\020MANUAL_AUT" +
+ "OMATIC\020\004\"\"\n\023NetworkDataSettings\022\013\n\003APN\030\001" +
+ " \001(\t\"3\n\025ServerConnectSettings\022\014\n\004host\030\001 " +
+ "\001(\t\022\014\n\004port\030\002 \001(\r\"\325\001\n\031ModemConfiguration" +
+ "Command\022@\n\027networkOperatorSettings\030\001 \001(\013" +
+ "2\037.openxc.NetworkOperatorSettings\0228\n\023net" +
+ "workDataSettings\030\002 \001(\0132\033.openxc.NetworkD" +
+ "ataSettings\022<\n\025serverConnectSettings\030\003 \001" +
+ "(\0132\035.openxc.ServerConnectSettings\",\n\027RTC" +
+ "ConfigurationCommand\022\021\n\tunix_time\030\001 \001(\r\"" +
+ "]\n\017CommandResponse\022)\n\004type\030\001 \001(\0162\033.openx" +
+ "c.ControlCommand.Type\022\017\n\007message\030\002 \001(\t\022\016" +
+ "\n\006status\030\003 \001(\010\"\375\001\n\021DiagnosticRequest\022\013\n\003" +
+ "bus\030\001 \001(\005\022\022\n\nmessage_id\030\002 \001(\r\022\014\n\004mode\030\003 " +
+ "\001(\r\022\013\n\003pid\030\004 \001(\r\022\017\n\007payload\030\005 \001(\014\022\032\n\022mul" +
+ "tiple_responses\030\006 \001(\010\022\021\n\tfrequency\030\007 \001(\001" +
+ "\022\014\n\004name\030\010 \001(\t\022;\n\014decoded_type\030\t \001(\0162%.o" +
+ "penxc.DiagnosticRequest.DecodedType\"!\n\013D" +
+ "ecodedType\022\010\n\004NONE\020\001\022\010\n\004OBD2\020\002\"\241\001\n\022Diagn" +
+ "osticResponse\022\013\n\003bus\030\001 \001(\005\022\022\n\nmessage_id" +
+ "\030\002 \001(\r\022\014\n\004mode\030\003 \001(\r\022\013\n\003pid\030\004 \001(\r\022\017\n\007suc" +
+ "cess\030\005 \001(\010\022\036\n\026negative_response_code\030\006 \001" +
+ "(\r\022\017\n\007payload\030\007 \001(\014\022\r\n\005value\030\010 \001(\001\"\242\001\n\014D" +
+ "ynamicField\022\'\n\004type\030\001 \001(\0162\031.openxc.Dynam" +
+ "icField.Type\022\024\n\014string_value\030\002 \001(\t\022\025\n\rnu" +
+ "meric_value\030\003 \001(\001\022\025\n\rboolean_value\030\004 \001(\010" +
+ "\"%\n\004Type\022\n\n\006STRING\020\001\022\007\n\003NUM\020\002\022\010\n\004BOOL\020\003\"" +
+ "g\n\rSimpleMessage\022\014\n\004name\030\001 \001(\t\022#\n\005value\030" +
+ "\002 \001(\0132\024.openxc.DynamicField\022#\n\005event\030\003 \001" +
+ "(\0132\024.openxc.DynamicFieldB\034\n\ncom.openxcB\016" +
+ "BinaryMessages"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
- new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
- public com.google.protobuf.ExtensionRegistry assignDescriptors(
- com.google.protobuf.Descriptors.FileDescriptor root) {
- descriptor = root;
- return null;
- }
- };
+ new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ return null;
+ }
+ };
com.google.protobuf.Descriptors.FileDescriptor
- .internalBuildGeneratedFileFrom(descriptorData,
- new com.google.protobuf.Descriptors.FileDescriptor[] {
- }, assigner);
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
internal_static_openxc_VehicleMessage_descriptor =
- getDescriptor().getMessageTypes().get(0);
+ getDescriptor().getMessageTypes().get(0);
internal_static_openxc_VehicleMessage_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_VehicleMessage_descriptor,
- new java.lang.String[] { "Type", "CanMessage", "SimpleMessage", "DiagnosticResponse", "ControlCommand", "CommandResponse", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_VehicleMessage_descriptor,
+ new java.lang.String[] { "Type", "CanMessage", "SimpleMessage", "DiagnosticResponse", "ControlCommand", "CommandResponse", "Timestamp", });
internal_static_openxc_CanMessage_descriptor =
- getDescriptor().getMessageTypes().get(1);
+ getDescriptor().getMessageTypes().get(1);
internal_static_openxc_CanMessage_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_CanMessage_descriptor,
- new java.lang.String[] { "Bus", "Id", "Data", "FrameFormat", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_CanMessage_descriptor,
+ new java.lang.String[] { "Bus", "Id", "Data", "FrameFormat", });
internal_static_openxc_ControlCommand_descriptor =
- getDescriptor().getMessageTypes().get(2);
+ getDescriptor().getMessageTypes().get(2);
internal_static_openxc_ControlCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_ControlCommand_descriptor,
- new java.lang.String[] { "Type", "DiagnosticRequest", "PassthroughModeRequest", "AcceptanceFilterBypassCommand", "PayloadFormatCommand", "PredefinedObd2RequestsCommand", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_ControlCommand_descriptor,
+ new java.lang.String[] { "Type", "DiagnosticRequest", "PassthroughModeRequest", "AcceptanceFilterBypassCommand", "PayloadFormatCommand", "PredefinedObd2RequestsCommand", "ModemConfigurationCommand", "RtcConfigurationCommand", });
internal_static_openxc_DiagnosticControlCommand_descriptor =
- getDescriptor().getMessageTypes().get(3);
+ getDescriptor().getMessageTypes().get(3);
internal_static_openxc_DiagnosticControlCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_DiagnosticControlCommand_descriptor,
- new java.lang.String[] { "Request", "Action", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_DiagnosticControlCommand_descriptor,
+ new java.lang.String[] { "Request", "Action", });
internal_static_openxc_PassthroughModeControlCommand_descriptor =
- getDescriptor().getMessageTypes().get(4);
+ getDescriptor().getMessageTypes().get(4);
internal_static_openxc_PassthroughModeControlCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_PassthroughModeControlCommand_descriptor,
- new java.lang.String[] { "Bus", "Enabled", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_PassthroughModeControlCommand_descriptor,
+ new java.lang.String[] { "Bus", "Enabled", });
internal_static_openxc_AcceptanceFilterBypassCommand_descriptor =
- getDescriptor().getMessageTypes().get(5);
+ getDescriptor().getMessageTypes().get(5);
internal_static_openxc_AcceptanceFilterBypassCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_AcceptanceFilterBypassCommand_descriptor,
- new java.lang.String[] { "Bus", "Bypass", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_AcceptanceFilterBypassCommand_descriptor,
+ new java.lang.String[] { "Bus", "Bypass", });
internal_static_openxc_PayloadFormatCommand_descriptor =
- getDescriptor().getMessageTypes().get(6);
+ getDescriptor().getMessageTypes().get(6);
internal_static_openxc_PayloadFormatCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_PayloadFormatCommand_descriptor,
- new java.lang.String[] { "Format", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_PayloadFormatCommand_descriptor,
+ new java.lang.String[] { "Format", });
internal_static_openxc_PredefinedObd2RequestsCommand_descriptor =
- getDescriptor().getMessageTypes().get(7);
+ getDescriptor().getMessageTypes().get(7);
internal_static_openxc_PredefinedObd2RequestsCommand_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_PredefinedObd2RequestsCommand_descriptor,
- new java.lang.String[] { "Enabled", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_PredefinedObd2RequestsCommand_descriptor,
+ new java.lang.String[] { "Enabled", });
+ internal_static_openxc_NetworkOperatorSettings_descriptor =
+ getDescriptor().getMessageTypes().get(8);
+ internal_static_openxc_NetworkOperatorSettings_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_NetworkOperatorSettings_descriptor,
+ new java.lang.String[] { "AllowDataRoaming", "OperatorSelectMode", "NetworkDescriptor", });
+ internal_static_openxc_NetworkOperatorSettings_NetworkDescriptor_descriptor =
+ internal_static_openxc_NetworkOperatorSettings_descriptor.getNestedTypes().get(0);
+ internal_static_openxc_NetworkOperatorSettings_NetworkDescriptor_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_NetworkOperatorSettings_NetworkDescriptor_descriptor,
+ new java.lang.String[] { "PLMN", "NetworkType", });
+ internal_static_openxc_NetworkDataSettings_descriptor =
+ getDescriptor().getMessageTypes().get(9);
+ internal_static_openxc_NetworkDataSettings_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_NetworkDataSettings_descriptor,
+ new java.lang.String[] { "APN", });
+ internal_static_openxc_ServerConnectSettings_descriptor =
+ getDescriptor().getMessageTypes().get(10);
+ internal_static_openxc_ServerConnectSettings_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_ServerConnectSettings_descriptor,
+ new java.lang.String[] { "Host", "Port", });
+ internal_static_openxc_ModemConfigurationCommand_descriptor =
+ getDescriptor().getMessageTypes().get(11);
+ internal_static_openxc_ModemConfigurationCommand_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_ModemConfigurationCommand_descriptor,
+ new java.lang.String[] { "NetworkOperatorSettings", "NetworkDataSettings", "ServerConnectSettings", });
+ internal_static_openxc_RTCConfigurationCommand_descriptor =
+ getDescriptor().getMessageTypes().get(12);
+ internal_static_openxc_RTCConfigurationCommand_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_RTCConfigurationCommand_descriptor,
+ new java.lang.String[] { "UnixTime", });
internal_static_openxc_CommandResponse_descriptor =
- getDescriptor().getMessageTypes().get(8);
+ getDescriptor().getMessageTypes().get(13);
internal_static_openxc_CommandResponse_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_CommandResponse_descriptor,
- new java.lang.String[] { "Type", "Message", "Status", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_CommandResponse_descriptor,
+ new java.lang.String[] { "Type", "Message", "Status", });
internal_static_openxc_DiagnosticRequest_descriptor =
- getDescriptor().getMessageTypes().get(9);
+ getDescriptor().getMessageTypes().get(14);
internal_static_openxc_DiagnosticRequest_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_DiagnosticRequest_descriptor,
- new java.lang.String[] { "Bus", "MessageId", "Mode", "Pid", "Payload", "MultipleResponses", "Frequency", "Name", "DecodedType", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_DiagnosticRequest_descriptor,
+ new java.lang.String[] { "Bus", "MessageId", "Mode", "Pid", "Payload", "MultipleResponses", "Frequency", "Name", "DecodedType", });
internal_static_openxc_DiagnosticResponse_descriptor =
- getDescriptor().getMessageTypes().get(10);
+ getDescriptor().getMessageTypes().get(15);
internal_static_openxc_DiagnosticResponse_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_DiagnosticResponse_descriptor,
- new java.lang.String[] { "Bus", "MessageId", "Mode", "Pid", "Success", "NegativeResponseCode", "Payload", "Value", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_DiagnosticResponse_descriptor,
+ new java.lang.String[] { "Bus", "MessageId", "Mode", "Pid", "Success", "NegativeResponseCode", "Payload", "Value", });
internal_static_openxc_DynamicField_descriptor =
- getDescriptor().getMessageTypes().get(11);
+ getDescriptor().getMessageTypes().get(16);
internal_static_openxc_DynamicField_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_DynamicField_descriptor,
- new java.lang.String[] { "Type", "StringValue", "NumericValue", "BooleanValue", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_DynamicField_descriptor,
+ new java.lang.String[] { "Type", "StringValue", "NumericValue", "BooleanValue", });
internal_static_openxc_SimpleMessage_descriptor =
- getDescriptor().getMessageTypes().get(12);
+ getDescriptor().getMessageTypes().get(17);
internal_static_openxc_SimpleMessage_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessage.FieldAccessorTable(
- internal_static_openxc_SimpleMessage_descriptor,
- new java.lang.String[] { "Name", "Value", "Event", });
+ com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_openxc_SimpleMessage_descriptor,
+ new java.lang.String[] { "Name", "Value", "Event", });
}
// @@protoc_insertion_point(outer_class_scope)
diff --git a/library/src/main/java/com/openxc/VehicleManager.java b/library/src/main/java/com/openxc/VehicleManager.java
index cfacbb034..aee65e0fc 100644
--- a/library/src/main/java/com/openxc/VehicleManager.java
+++ b/library/src/main/java/com/openxc/VehicleManager.java
@@ -1,10 +1,5 @@
package com.openxc;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
@@ -40,6 +35,11 @@
import com.openxc.sources.RemoteListenerSource;
import com.openxc.sources.VehicleDataSource;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
/**
* The VehicleManager is an in-process Android service and the primary entry
* point into the OpenXC library.
diff --git a/library/src/main/java/com/openxc/interfaces/bluetooth/BLEInputStream.java b/library/src/main/java/com/openxc/interfaces/bluetooth/BLEInputStream.java
new file mode 100644
index 000000000..172e47c1c
--- /dev/null
+++ b/library/src/main/java/com/openxc/interfaces/bluetooth/BLEInputStream.java
@@ -0,0 +1,65 @@
+package com.openxc.interfaces.bluetooth;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+
+/**
+ * Created by AKUMA128 on 2/9/2018.
+ */
+
+public class BLEInputStream extends InputStream {
+ public static final int MAX_READ_BUFFER_CAPACITY = 4096;
+ private static final String TAG = BLEInputStream.class.getSimpleName();
+ private static BLEInputStream bleInputStream = null;
+
+ private ByteBuffer buf = ByteBuffer.allocate(MAX_READ_BUFFER_CAPACITY);
+
+ public static BLEInputStream getInstance() {
+ if (bleInputStream == null) {
+ bleInputStream = new BLEInputStream();
+ }
+ return bleInputStream;
+ }
+
+ public int read() throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+ return buf.get() & 0xFF;
+ }
+
+ public synchronized int read(byte[] bytes, int off, int len)
+ throws IOException {
+ buf.flip();
+ int bufferLength = buf.limit();
+ try {
+ buf.get(bytes, off, bufferLength);
+ } catch (BufferUnderflowException e) {
+ Log.d(TAG, "BufferUnderflow bufferLength : " + bufferLength);
+ }
+ buf.clear();
+ return bufferLength;
+ }
+
+ public synchronized void putDataInBuffer(byte[] data) {
+ try {
+ buf.put(data);
+ } catch (BufferOverflowException e) {
+ Log.e(TAG, "Buffer overflowing Resetting!!!!");
+ buf.clear();
+ }
+ }
+
+ public boolean doesBufferHasRemaining() {
+ return buf.position() > 0;
+ }
+
+ public void clearBuffer() {
+ buf.clear();
+ }
+}
diff --git a/library/src/main/java/com/openxc/interfaces/bluetooth/BluetoothVehicleInterface.java b/library/src/main/java/com/openxc/interfaces/bluetooth/BluetoothVehicleInterface.java
index eac208d0a..6994de0f6 100644
--- a/library/src/main/java/com/openxc/interfaces/bluetooth/BluetoothVehicleInterface.java
+++ b/library/src/main/java/com/openxc/interfaces/bluetooth/BluetoothVehicleInterface.java
@@ -1,15 +1,9 @@
package com.openxc.interfaces.bluetooth;
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
@@ -22,7 +16,6 @@
import android.util.Log;
import com.google.common.base.MoreObjects;
-
import com.openxc.interfaces.VehicleInterface;
import com.openxc.sources.BytestreamDataSource;
import com.openxc.sources.DataSourceException;
@@ -30,21 +23,28 @@
import com.openxc.sources.SourceCallback;
import com.openxcplatform.R;
+import java.io.BufferedInputStream;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
/**
* A vehicle data source reading measurements from an Bluetooth-enabled
* OpenXC device.
- *
+ *
* This class tries to connect to a previously paired Bluetooth device with a
* given MAC address. If found, it opens a socket to the device and streams
* both read and write OpenXC messages.
- *
+ *
* This class requires both the android.permission.BLUETOOTH and
* android.permission.BLUETOOTH_ADMIN permissions.
*/
public class BluetoothVehicleInterface extends BytestreamDataSource
implements VehicleInterface {
- private static final String TAG = "BluetoothVehicleInterface";
- public static final String DEVICE_NAME_PREFIX = "OpenXC-VI-";
+ private static final String TAG = BluetoothVehicleInterface.class.getSimpleName();
+ public static final String DEVICE_NAME_PREFIX = "OPENXC-VI-";
private DeviceManager mDeviceManager;
private Thread mAcceptThread;
@@ -57,12 +57,17 @@ public class BluetoothVehicleInterface extends BytestreamDataSource
private boolean mUsePolling = false;
private boolean mSocketAccepterRunning = true;
+ private BluetoothGatt mBluetoothGatt;
+
+ private boolean connectingToBLE = false;
+ BLEInputStream mBLEInputStream;
+
public BluetoothVehicleInterface(SourceCallback callback, Context context,
- String address) throws DataSourceException {
+ String address) throws DataSourceException {
super(callback, context);
try {
mDeviceManager = new DeviceManager(getContext());
- } catch(BluetoothException e) {
+ } catch (BluetoothException e) {
throw new DataSourceException(
"Unable to open Bluetooth device manager", e);
}
@@ -95,7 +100,7 @@ public BluetoothVehicleInterface(Context context, String address)
/**
* Control whether periodic polling is used to detect a Bluetooth VI.
- *
+ *
* This class opens a Bluetooth socket and will accept incoming connections
* from a VI that can act as the Bluetooth master. For VIs that are only
* able to act as slave, we have to poll for a connection occasionally to
@@ -108,27 +113,35 @@ public void setPollingStatus(boolean enabled) {
@Override
public boolean setResource(String otherAddress) throws DataSourceException {
boolean reconnect = false;
- if(isConnected()) {
- if(otherAddress == null) {
+ if (isConnected()) {
+ if (otherAddress == null) {
// switch to automatic but don't break the existing connection
reconnect = false;
- } else if(!sameResource(mConnectedAddress, otherAddress) &&
+ } else if (!sameResource(mConnectedAddress, otherAddress) &&
!sameResource(mExplicitAddress, otherAddress)) {
reconnect = true;
}
}
setAddress(otherAddress);
-
- if(reconnect) {
- try {
- if(mSocket != null) {
- mSocket.close();
+ Log.d(TAG, "Setting address " + otherAddress);
+ if (reconnect) {
+ if (!connectingToBLE) {
+ try {
+ if (mSocket != null) {
+ mSocket.close();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "Exception occurred while closing the socket");
+ }
+ } else {
+ if (mBluetoothGatt != null) {
+ mBluetoothGatt.close();
}
- } catch(IOException e) {
}
setFastPolling(true);
}
+
return reconnect;
}
@@ -139,31 +152,43 @@ public boolean isConnected() {
// If we can't get the lock in 100ms, must be blocked waiting for a
// connection so we consider it disconnected.
try {
- if(mConnectionLock.readLock().tryLock(100, TimeUnit.MILLISECONDS)) {
+ if (mConnectionLock.readLock().tryLock(100, TimeUnit.MILLISECONDS)) {
connected = super.isConnected();
- if(mSocket == null) {
- connected = false;
+ if (!connectingToBLE) {
+ if (mSocket == null) {
+ connected = false;
+ } else {
+ try {
+ connected &= mSocket.isConnected();
+
+ } catch (NoSuchMethodError e) {
+ // Cannot get isConnected() result before API 14
+ // Assume previous result is correct.
+ }
+ }
} else {
- try {
- connected &= mSocket.isConnected();
- } catch (NoSuchMethodError e) {
- // Cannot get isConnected() result before API 14
- // Assume previous result is correct.
+ if (mBluetoothGatt == null) {
+ connected = false;
+ } else {
+ if (mConnectedAddress != null)
+ connected = true;
+ else connected = false;
}
}
mConnectionLock.readLock().unlock();
}
- } catch(InterruptedException e) { }
+ } catch (InterruptedException e) {
+ }
return connected;
}
@Override
public synchronized void stop() {
- if(isRunning()) {
+ if (isRunning()) {
try {
getContext().unregisterReceiver(mBroadcastReceiver);
- } catch(IllegalArgumentException e) {
+ } catch (IllegalArgumentException e) {
Log.w(TAG, "Broadcast receiver not registered but we expected it to be");
}
mDeviceManager.stop();
@@ -175,10 +200,11 @@ public synchronized void stop() {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
- .add("explicitDeviceAddress", mExplicitAddress)
- .add("connectedDeviceAddress", mConnectedAddress)
- .add("socket", mSocket)
- .toString();
+ .add("explicitDeviceAddress", mExplicitAddress)
+ .add("connectedDeviceAddress", mConnectedAddress)
+ .add("socket", mSocket)
+ .add("bluetoothGatt", mBluetoothGatt)
+ .toString();
}
private class SocketAccepter implements Runnable {
@@ -188,12 +214,13 @@ private class SocketAccepter implements Runnable {
public void run() {
Log.d(TAG, "Socket accepter starting up");
BluetoothSocket socket = null;
- while(isRunning() && shouldAttemptConnection()) {
- while(isConnected()) {
+ while (isRunning() && shouldAttemptConnection()) {
+
+ while (isConnected()) {
mConnectionLock.writeLock().lock();
try {
mDeviceChanged.await();
- } catch(InterruptedException e) {
+ } catch (InterruptedException e) {
} finally {
mConnectionLock.writeLock().unlock();
@@ -205,14 +232,11 @@ public void run() {
// while(isConnected()) loop and land here - double check that
// this interface should still be running before trying to make
// another connection.
- if(!isRunning()) {
+ if (!isRunning()) {
break;
}
- Log.d(TAG, "Initializing listening socket");
- mmServerSocket = mDeviceManager.listen();
-
- if(mmServerSocket == null) {
+ if (mmServerSocket == null) {
Log.i(TAG, "Unable to listen for Bluetooth connections " +
"- adapter may be off");
stopWhileBluetoothDisabled();
@@ -225,13 +249,14 @@ public void run() {
} catch (IOException e) {
}
- if(socket != null) {
+ if (socket != null) {
Log.i(TAG, "New inbound socket connection accepted");
manageConnectedSocket(socket);
try {
Log.d(TAG, "Closing listening server socket");
mmServerSocket.close();
- } catch (IOException e) { }
+ } catch (IOException e) {
+ }
}
}
Log.d(TAG, "SocketAccepter is stopping");
@@ -241,15 +266,17 @@ public void run() {
public void stop() {
try {
- if(mmServerSocket != null) {
+ if (mmServerSocket != null) {
mmServerSocket.close();
}
- } catch (IOException e) { }
+ } catch (IOException e) {
+ }
}
}
+
@Override
protected void connect() {
- if(!mUsePolling || !isRunning()) {
+ if (!mUsePolling || !isRunning()) {
return;
}
@@ -259,21 +286,29 @@ protected void connect() {
mDeviceManager.getLastConnectedDevice();
BluetoothSocket newSocket = null;
- if(mExplicitAddress != null || !mPerformAutomaticScan) {
+ BluetoothGatt bluetoothGatt = null;
+ if (mExplicitAddress != null || !mPerformAutomaticScan) {
String address = mExplicitAddress;
- if(address == null && lastConnectedDevice != null) {
+ if (address == null && lastConnectedDevice != null) {
address = lastConnectedDevice.getAddress();
}
- if(address != null) {
- Log.i(TAG, "Connecting to Bluetooth device " + address);
+ if (address != null) {
+ Log.i(TAG, "Connecting to Bluetooth device " + address + " device is BLE : " + mDeviceManager.isBLEDevice(address));
try {
- if(!isConnected()) {
- newSocket = mDeviceManager.connect(address);
+ if (!isConnected()) {
+ if (!mDeviceManager.isBLEDevice(address)) {
+ connectingToBLE = false;
+ newSocket = mDeviceManager.connect(address);
+ } else if (!mDeviceManager.isBLEConnected()) {
+ connectingToBLE = true;
+ bluetoothGatt = mDeviceManager.connectBLE(address);
+ }
}
- } catch(BluetoothException e) {
+ } catch (BluetoothException e) {
Log.w(TAG, "Unable to connect to device " + address, e);
newSocket = null;
+ bluetoothGatt = null;
}
} else {
Log.d(TAG, "No detected or stored Bluetooth device MAC, not attempting connection");
@@ -286,31 +321,38 @@ protected void connect() {
Log.v(TAG, "Attempting automatic detection of Bluetooth VI");
ArrayList candidateDevices =
- new ArrayList<>(
- mDeviceManager.getCandidateDevices());
+ new ArrayList<>(
+ mDeviceManager.getCandidateDevices());
- if(lastConnectedDevice != null) {
+ if (lastConnectedDevice != null) {
Log.v(TAG, "First trying last connected BT VI: " +
lastConnectedDevice);
candidateDevices.add(0, lastConnectedDevice);
}
- for(BluetoothDevice device : candidateDevices) {
+ for (BluetoothDevice device : candidateDevices) {
try {
- if(!isConnected()) {
+ if (!isConnected()) {
Log.i(TAG, "Attempting connection to auto-detected " +
"VI " + device);
- newSocket = mDeviceManager.connect(device);
+ if (!mDeviceManager.isBLEDevice(device)) {
+ connectingToBLE = false;
+ newSocket = mDeviceManager.connect(device);
+ } else {
+ connectingToBLE = true;
+ bluetoothGatt = mDeviceManager.connectBLE(device);
+ }
break;
}
- } catch(BluetoothException e) {
+ } catch (BluetoothException e) {
Log.w(TAG, "Unable to connect to auto-detected device " +
device, e);
newSocket = null;
+ bluetoothGatt = null;
}
}
- if(lastConnectedDevice == null && newSocket == null
+ if (lastConnectedDevice == null && newSocket == null
&& candidateDevices.size() > 0) {
Log.i(TAG, "No BT VI ever connected, and none of " +
"discovered devices could connect - storing " +
@@ -320,20 +362,44 @@ protected void connect() {
candidateDevices.get(0));
}
}
+ if (connectingToBLE && bluetoothGatt != null) {
+ manageConnectedGatt(bluetoothGatt);
+ } else if(!connectingToBLE){
+ manageConnectedSocket(newSocket);
+ }
+ }
- manageConnectedSocket(newSocket);
+ private void manageConnectedGatt(BluetoothGatt bluetoothGatt) {
+ mConnectionLock.writeLock().lock();
+ try {
+ mBluetoothGatt = bluetoothGatt;
+ if (mBluetoothGatt != null) {
+ try {
+ connectStreams();
+ connected();
+ mConnectedAddress = mBluetoothGatt.getDevice().getAddress();
+ } catch (BluetoothException e) {
+ Log.d(TAG, "Unable to open Bluetooth streams", e);
+ disconnected();
+ }
+ } else {
+ disconnected();
+ }
+ } finally {
+ mConnectionLock.writeLock().unlock();
+ }
}
private synchronized void manageConnectedSocket(BluetoothSocket socket) {
mConnectionLock.writeLock().lock();
try {
mSocket = socket;
- if(mSocket != null) {
+ if (mSocket != null) {
try {
connectStreams();
connected();
mConnectedAddress = mSocket.getRemoteDevice().getAddress();
- } catch(BluetoothException e) {
+ } catch (BluetoothException e) {
Log.d(TAG, "Unable to open Bluetooth streams", e);
disconnected();
}
@@ -349,9 +415,20 @@ private synchronized void manageConnectedSocket(BluetoothSocket socket) {
protected int read(byte[] bytes) throws IOException {
mConnectionLock.readLock().lock();
int bytesRead = -1;
+ if (connectingToBLE) {
+ bytesRead = 0;
+ }
try {
- if(isConnected()) {
+ if (isConnected() && !connectingToBLE) {
bytesRead = mInStream.read(bytes, 0, bytes.length);
+ } else if (isConnected()) {
+ if (mBLEInputStream != null && mBLEInputStream.doesBufferHasRemaining()) {
+ bytesRead = mInStream.read(bytes, 0, bytes.length);
+ } else if (mDeviceManager.isBLEDisconnected()) {
+ //Disconnect BLE if GattCallBack state changed to disconnected
+ mConnectedAddress = null;
+ bytesRead = -1;
+ }
}
} finally {
mConnectionLock.readLock().unlock();
@@ -363,16 +440,19 @@ protected boolean write(byte[] bytes) {
mConnectionLock.readLock().lock();
boolean success = false;
try {
- if(isConnected()) {
+ if (isConnected() && !connectingToBLE) {
mOutStream.write(new String(bytes));
// TODO what if we didn't flush every time? might be faster for
// sustained writes.
mOutStream.flush();
success = true;
+ } else if (isConnected() && connectingToBLE && !mDeviceManager.isBLEDisconnected()) {
+ mDeviceManager.writeCharacteristicToBLE(bytes);
+ success = true;
} else {
Log.w(TAG, "Unable to write -- not connected");
}
- } catch(IOException e) {
+ } catch (IOException e) {
Log.d(TAG, "Error writing to stream", e);
} finally {
mConnectionLock.readLock().unlock();
@@ -385,39 +465,47 @@ private synchronized void closeSocket() {
// lock - we also want to forcefully break the connection NOW instead of
// waiting for the lock if BT is going down
try {
- if(mSocket != null) {
+ if (mSocket != null) {
mSocket.close();
Log.d(TAG, "Disconnected from the socket");
}
- } catch(IOException e) {
+ } catch (IOException e) {
Log.w(TAG, "Unable to close the socket", e);
} finally {
mSocket = null;
}
}
+ private synchronized void closeGatt() {
+ if (mBluetoothGatt != null) {
+ mBluetoothGatt.close();
+ Log.d(TAG, "Disconnected from the gatt");
+ }
+ }
+
@Override
protected void disconnect() {
closeSocket();
+ closeGatt();
mConnectionLock.writeLock().lock();
try {
try {
- if(mInStream != null) {
+ if (mInStream != null) {
mInStream.close();
Log.d(TAG, "Disconnected from the input stream");
}
- } catch(IOException e) {
+ } catch (IOException e) {
Log.w(TAG, "Unable to close the input stream", e);
} finally {
mInStream = null;
}
try {
- if(mOutStream != null) {
+ if (mOutStream != null) {
mOutStream.close();
Log.d(TAG, "Disconnected from the output stream");
}
- } catch(IOException e) {
+ } catch (IOException e) {
Log.w(TAG, "Unable to close the output stream", e);
} finally {
mOutStream = null;
@@ -437,16 +525,24 @@ protected String getTag() {
private void connectStreams() throws BluetoothException {
mConnectionLock.writeLock().lock();
try {
- try {
- mOutStream = new BufferedWriter(new OutputStreamWriter(
+ if (!connectingToBLE) {
+ try {
+ mOutStream = new BufferedWriter(new OutputStreamWriter(
mSocket.getOutputStream()));
- mInStream = new BufferedInputStream(mSocket.getInputStream());
- Log.i(TAG, "Socket stream to vehicle interface " +
+ mInStream = new BufferedInputStream(mSocket.getInputStream());
+ Log.i(TAG, "Socket stream to vehicle interface " +
+ "opened successfully");
+ } catch (IOException e) {
+ Log.e(TAG, "Error opening streams ", e);
+ disconnect();
+ throw new BluetoothException();
+ }
+ } else {
+ mBLEInputStream = BLEInputStream.getInstance();
+ mBLEInputStream.clearBuffer();
+ mInStream = new BufferedInputStream(mBLEInputStream);
+ Log.i(TAG, "Input stream to vehicle interface " +
"opened successfully");
- } catch(IOException e) {
- Log.e(TAG, "Error opening streams ", e);
- disconnect();
- throw new BluetoothException();
}
} finally {
mConnectionLock.writeLock().unlock();
@@ -454,7 +550,7 @@ private void connectStreams() throws BluetoothException {
}
private void setAddress(String address) throws DataSourceResourceException {
- if(address != null && !BluetoothAdapter.checkBluetoothAddress(address)) {
+ if (address != null && !BluetoothAdapter.checkBluetoothAddress(address)) {
throw new DataSourceResourceException("\"" + address +
"\" is not a valid MAC address");
}
@@ -478,37 +574,38 @@ private void stopWhileBluetoothDisabled() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED) ||
+ if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED) ||
action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
// Whenever discovery finishes or another Bluetooth device connects
// (i.e. it might be a car's infotainment system), take the
// opportunity to try and connect to detected devices if we're not
// already connected. Discovery may have been initiated by the
// Enabler UI, or by some other user action or app.
- if(mUsePolling && !isConnected() && !mDeviceManager.isConnecting()) {
+ if (mUsePolling && !isConnected() && !mDeviceManager.isConnecting()) {
Log.d(TAG, "Discovery finished or a device connected, but " +
"we are not connected or attempting connections - " +
"kicking off reconnection attempts");
- if(mExplicitAddress == null) {
+ if (mExplicitAddress == null) {
mPerformAutomaticScan = true;
}
setFastPolling(true);
}
- } else if(action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+ } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
- case BluetoothAdapter.STATE_OFF:
- Log.d(TAG, "Bluetooth adapter turned off");
- stopWhileBluetoothDisabled();
- break;
- case BluetoothAdapter.STATE_ON:
- Log.d(TAG, "Bluetooth adapter turned on");
- mSocketAccepterRunning = true;
- setFastPolling(true);
- mAcceptThread = new Thread(new SocketAccepter());
- mAcceptThread.start();
- break;
+ case BluetoothAdapter.STATE_OFF:
+ Log.d(TAG, "Bluetooth adapter turned off");
+ stopWhileBluetoothDisabled();
+ break;
+ case BluetoothAdapter.STATE_ON:
+ Log.d(TAG, "Bluetooth adapter turned on");
+ mBluetoothGatt = null;
+ mSocketAccepterRunning = true;
+ setFastPolling(true);
+ mAcceptThread = new Thread(new SocketAccepter());
+ mAcceptThread.start();
+ break;
}
}
}
diff --git a/library/src/main/java/com/openxc/interfaces/bluetooth/DeviceManager.java b/library/src/main/java/com/openxc/interfaces/bluetooth/DeviceManager.java
index e12195b42..ff4740cdc 100644
--- a/library/src/main/java/com/openxc/interfaces/bluetooth/DeviceManager.java
+++ b/library/src/main/java/com/openxc/interfaces/bluetooth/DeviceManager.java
@@ -1,13 +1,10 @@
package com.openxc.interfaces.bluetooth;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
@@ -17,10 +14,18 @@
import com.openxc.util.SupportSettingsUtils;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.BufferOverflowException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
/**
* The DeviceManager collects the functions required to connect to and open a
* socket to the Bluetooth device.
- *
+ *
* The device must be previously bonded, as this class does not initiate
* discovery.
*/
@@ -36,6 +41,14 @@ public class DeviceManager {
private BluetoothSocket mSocket;
private AtomicBoolean mSocketConnecting = new AtomicBoolean(false);
private Context mContext;
+ private BluetoothGatt mBluetoothGatt;
+ private GattCallback mGattCallback;
+
+ public static final int MAX_WRITE_BUFFER_CAPACITY = 1024;
+ private byte[] writeArray = new byte[MAX_WRITE_BUFFER_CAPACITY];
+ private int queueEnd = 0;
+ public static final int PACKET_SENDING_WAIT_TIME_MS = 50;
+
/**
* The DeviceManager requires an Android Context in order to send the intent
@@ -43,7 +56,7 @@ public class DeviceManager {
*/
public DeviceManager(Context context) throws BluetoothException {
mContext = context;
- if(getDefaultAdapter() == null) {
+ if (getDefaultAdapter() == null) {
String message = "This device most likely does not have " +
"a Bluetooth adapter";
Log.w(TAG, message);
@@ -54,10 +67,10 @@ public DeviceManager(Context context) throws BluetoothException {
}
private BluetoothAdapter getDefaultAdapter() {
- if(mBluetoothAdapter == null) {
+ if (mBluetoothAdapter == null) {
// work around an Android bug, requires that this is called before
// getting the default adapter
- if(Looper.myLooper() == null) {
+ if (Looper.myLooper() == null) {
Looper.prepare();
}
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -66,8 +79,8 @@ private BluetoothAdapter getDefaultAdapter() {
}
public void startDiscovery() {
- if(getDefaultAdapter() != null) {
- if(getDefaultAdapter().isDiscovering()) {
+ if (getDefaultAdapter() != null) {
+ if (getDefaultAdapter().isDiscovering()) {
getDefaultAdapter().cancelDiscovery();
}
Log.i(TAG, "Starting Bluetooth discovery");
@@ -81,14 +94,15 @@ public BluetoothServerSocket listen() {
// TODO use an OpenXC-specific UUID
tmp = getDefaultAdapter().listenUsingRfcommWithServiceRecord(
"TODO", DeviceManager.RFCOMM_UUID);
- } catch (IOException e) { }
+ } catch (IOException e) {
+ }
return tmp;
}
/**
* Connect to the target device and open a socket. This method will block
* while waiting for the device.
- *
+ *
* Returns a socket connected to the device.
*/
public BluetoothSocket connect(String targetAddress)
@@ -98,7 +112,7 @@ public BluetoothSocket connect(String targetAddress)
public BluetoothSocket connect(BluetoothDevice device)
throws BluetoothException {
- if(device == null) {
+ if (device == null) {
throw new BluetoothException("Not connecting to null Bluetooth device");
}
mSocket = setupSocket(device);
@@ -110,11 +124,11 @@ public BluetoothSocket connect(BluetoothDevice device)
/**
* Immediately cancel any pending Bluetooth operations.
- *
+ *
* The BluetoothSocket.connect() function blocks while waiting for a
* connection, but it's thread safe and we can cancel that by calling
* close() on it at any time.
- *
+ *
* Importantly we don't want to close the socket any other time, because we
* want to leave that up to the user of the socket - if you call close()
* twice, or close Input/Output streams associated with the socket
@@ -122,20 +136,23 @@ public BluetoothSocket connect(BluetoothDevice device)
* Bluetooth stacks. Awesome!
*/
public void stop() {
- if(mSocketConnecting.get() && mSocket != null) {
+ if (mSocketConnecting.get() && mSocket != null) {
try {
mSocket.close();
- } catch(IOException e) { }
+ } catch (IOException e) {
+ }
}
-
- if(getDefaultAdapter() != null) {
+ if (mSocketConnecting.get() && mBluetoothGatt != null) {
+ mBluetoothGatt.close();
+ }
+ if (getDefaultAdapter() != null) {
getDefaultAdapter().cancelDiscovery();
}
}
public Set getPairedDevices() {
Set devices = new HashSet<>();
- if(getDefaultAdapter() != null && getDefaultAdapter().isEnabled()) {
+ if (getDefaultAdapter() != null && getDefaultAdapter().isEnabled()) {
devices = getDefaultAdapter().getBondedDevices();
}
return devices;
@@ -154,12 +171,12 @@ public void storeLastConnectedDevice(BluetoothDevice device) {
public BluetoothDevice getLastConnectedDevice() {
SharedPreferences preferences =
- mContext.getSharedPreferences(KNOWN_BLUETOOTH_DEVICE_PREFERENCES,
- Context.MODE_MULTI_PROCESS);
+ mContext.getSharedPreferences(KNOWN_BLUETOOTH_DEVICE_PREFERENCES,
+ Context.MODE_MULTI_PROCESS);
String lastConnectedDeviceAddress = preferences.getString(
- LAST_CONNECTED_BLUETOOTH_DEVICE_PREF_KEY, null);
+ LAST_CONNECTED_BLUETOOTH_DEVICE_PREF_KEY, null);
BluetoothDevice lastConnectedDevice = null;
- if(lastConnectedDeviceAddress != null) {
+ if (lastConnectedDeviceAddress != null) {
lastConnectedDevice = getDefaultAdapter().getRemoteDevice(lastConnectedDeviceAddress);
}
return lastConnectedDevice;
@@ -168,26 +185,26 @@ public BluetoothDevice getLastConnectedDevice() {
public Set getCandidateDevices() {
Set candidates = new HashSet<>();
- for(BluetoothDevice device : getPairedDevices()) {
- if(device.getName().startsWith(
- BluetoothVehicleInterface.DEVICE_NAME_PREFIX)) {
+ for (BluetoothDevice device : getPairedDevices()) {
+ if (device.getName().startsWith(
+ BluetoothVehicleInterface.DEVICE_NAME_PREFIX)) {
candidates.add(device);
}
}
SharedPreferences preferences =
mContext.getSharedPreferences(KNOWN_BLUETOOTH_DEVICE_PREFERENCES,
- Context.MODE_MULTI_PROCESS);
+ Context.MODE_MULTI_PROCESS);
Set detectedDevices = SupportSettingsUtils.getStringSet(
preferences, KNOWN_BLUETOOTH_DEVICE_PREF_KEY,
new HashSet());
- for(String address : detectedDevices) {
- if(BluetoothAdapter.checkBluetoothAddress(address)) {
+ for (String address : detectedDevices) {
+ if (BluetoothAdapter.checkBluetoothAddress(address)) {
candidates.add(getDefaultAdapter().getRemoteDevice(address));
}
}
- for(BluetoothDevice candidate : candidates) {
+ for (BluetoothDevice candidate : candidates) {
Log.d(TAG, "Found previously discovered or paired OpenXC BT VI "
+ candidate.getAddress());
}
@@ -202,15 +219,16 @@ private void connectToSocket(BluetoothSocket socket) throws BluetoothException {
mSocketConnecting.set(true);
try {
socket.connect();
- if(getDefaultAdapter().isDiscovering()) {
+ if (getDefaultAdapter().isDiscovering()) {
getDefaultAdapter().cancelDiscovery();
}
- } catch(IOException e) {
+ } catch (IOException e) {
String error = "Could not connect to SPP service on " + socket;
Log.e(TAG, error);
try {
socket.close();
- } catch(IOException e2) {}
+ } catch (IOException e2) {
+ }
throw new BluetoothException(error, e);
} finally {
mSocketConnecting.set(false);
@@ -219,13 +237,13 @@ private void connectToSocket(BluetoothSocket socket) throws BluetoothException {
/**
* Open an RFCOMM socket to the Bluetooth device.
- *
+ *
* The device may or may not actually exist, the argument is just a
* reference to it.
*/
private BluetoothSocket setupSocket(BluetoothDevice device)
throws BluetoothException {
- if(device == null) {
+ if (device == null) {
Log.w(TAG, "Can't setup socket -- device is null");
throw new BluetoothException();
}
@@ -234,7 +252,7 @@ private BluetoothSocket setupSocket(BluetoothDevice device)
BluetoothSocket socket;
try {
socket = device.createRfcommSocketToServiceRecord(RFCOMM_UUID);
- } catch(IOException e) {
+ } catch (IOException e) {
String error = "Unable to open a socket to device " + device;
Log.w(TAG, error);
throw new BluetoothException(error, e);
@@ -242,4 +260,123 @@ private BluetoothSocket setupSocket(BluetoothDevice device)
return socket;
}
+
+ public boolean isBLEDevice(String address) {
+
+ return getDefaultAdapter().
+ getRemoteDevice(address).
+ getType() == BluetoothDevice.DEVICE_TYPE_LE;
+ }
+
+ public boolean isBLEDevice(BluetoothDevice device) {
+ return device.getType() == BluetoothDevice.DEVICE_TYPE_LE;
+ }
+
+ public BluetoothGatt connectBLE(String address) throws BluetoothException {
+ return connectBLE(getDefaultAdapter().getRemoteDevice(address));
+ }
+
+ public BluetoothGatt connectBLE(BluetoothDevice device) throws BluetoothException {
+ if (device == null) {
+ throw new BluetoothException("Not connecting to null Bluetooth device");
+ }
+ mSocketConnecting.set(true);
+ try {
+ mGattCallback = new GattCallback();
+ mBluetoothGatt = device.connectGatt(mContext, true, mGattCallback);
+ mBluetoothGatt.connect();
+ mGattCallback.setBluetoothGatt(mBluetoothGatt);
+ Log.d(TAG, "Connected to gatt " + mBluetoothGatt);
+ if (getDefaultAdapter().isDiscovering()) {
+ getDefaultAdapter().cancelDiscovery();
+ }
+ } catch (IllegalArgumentException e) {
+ String error = "Unable to connect to GATT Server on BLE device " + device;
+ Log.w(TAG, error);
+ mBluetoothGatt.disconnect();
+ throw new BluetoothException(error, e);
+ } finally {
+ mSocketConnecting.set(false);
+ }
+ //storeLastConnectedDevice(device);
+ return mBluetoothGatt;
+ }
+
+ /***
+ * This is used to get the connection status using gatt callback
+ * @return boolean value indicating
+ */
+ public boolean isBLEConnected() {
+ if (mGattCallback != null) {
+ return mGattCallback.isConnected();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isBLEDisconnected() {
+ if (mGattCallback != null) {
+ return mGattCallback.isDisconnected();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean writeCharacteristicToBLE(byte[] bytes) {
+ try {
+ for (int i = 0; i < bytes.length; i++) {
+ writeArray[queueEnd++] = bytes[i];
+ }
+ } catch (BufferOverflowException e) {
+ Log.d(TAG, "Buffer overflowing!!!!");
+ return false;
+ }
+
+ BLESendData();
+ return true;
+ }
+
+ private void BLESendData() {
+ if (queueEnd <= 0) {
+ return;
+ }
+ if (mBluetoothGatt != null) {
+ BluetoothGattService openXCService = mBluetoothGatt.getService(UUID.fromString(GattCallback.C5_OPENXC_BLE_SERVICE_UUID));
+ if (openXCService != null) {
+ BluetoothGattCharacteristic characteristic = openXCService.getCharacteristic(UUID.fromString(GattCallback.C5_OPENXC_BLE_CHARACTERISTIC_WRITE_UUID));
+ if (characteristic != null) {
+
+ while (queueEnd != 0) {
+ byte[] sendingPacket;
+ if (queueEnd >= 20) {
+ sendingPacket = new byte[20];
+ System.arraycopy(writeArray, 0, sendingPacket, 0, 20);
+ System.arraycopy(writeArray, 20, writeArray, 0, queueEnd - 20);
+ queueEnd = queueEnd - 20;
+
+ } else {
+ sendingPacket = new byte[queueEnd];
+ System.arraycopy(writeArray, 0, sendingPacket, 0, queueEnd);
+ queueEnd = 0;
+ }
+ characteristic.setValue(sendingPacket);
+ try {
+ Thread.sleep(PACKET_SENDING_WAIT_TIME_MS);
+
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Interrupted");
+ e.printStackTrace();
+ }
+ mBluetoothGatt.writeCharacteristic(characteristic);
+ }
+ } else {
+ Log.d(TAG, "characteristic is null");
+ }
+ } else {
+ Log.d(TAG, "OpenXC Service not found!");
+ }
+ } else {
+ Log.d(TAG, "Gatt not found!");
+ }
+ }
}
diff --git a/library/src/main/java/com/openxc/interfaces/bluetooth/GattCallback.java b/library/src/main/java/com/openxc/interfaces/bluetooth/GattCallback.java
new file mode 100644
index 000000000..dbe6aacec
--- /dev/null
+++ b/library/src/main/java/com/openxc/interfaces/bluetooth/GattCallback.java
@@ -0,0 +1,120 @@
+package com.openxc.interfaces.bluetooth;
+
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothProfile;
+import android.util.Log;
+
+import com.openxc.messages.streamers.JsonStreamer;
+
+import java.util.UUID;
+
+/**
+ * Created by AKUMA128 on 2/9/2018.
+ */
+
+public class GattCallback extends BluetoothGattCallback {
+
+ private final static String TAG = GattCallback.class.getSimpleName();
+ public static final String C5_OPENXC_BLE_SERVICE_UUID = "6800D38B-423D-4BDB-BA05-C9276D8453E1";
+ public static final String C5_OPENXC_BLE_CHARACTERISTIC_NOTIFY_UUID = "6800D38B-5262-11E5-885D-FEFF819CDCE3";
+ public static final String C5_OPENXC_BLE_DESCRIPTOR_NOTIFY_UUID = "00002902-0000-1000-8000-00805f9b34fb";
+ public static final String C5_OPENXC_BLE_CHARACTERISTIC_WRITE_UUID = "6800D38B-5262-11E5-885D-FEFF819CDCE2";
+
+ private boolean isConnected = false;
+ private boolean isDisconnected = false;
+ private BluetoothGatt mBluetoothGatt;
+ private StringBuffer messageBuffer = new StringBuffer();
+ private final static String DELIMITER = "\u0000";
+
+ public void setBluetoothGatt(BluetoothGatt mBluetoothGatt) {
+ this.mBluetoothGatt = mBluetoothGatt;
+ }
+
+ @Override
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ super.onConnectionStateChange(gatt, status, newState);
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ setConnected(true);
+ Log.d(TAG, "Status BLE Connected");
+ // Attempts to discover services after successful connection.
+ if (mBluetoothGatt != null) {
+ boolean discoverServices = mBluetoothGatt.discoverServices();
+ Log.i(TAG, "Attempting to start service discovery:" + discoverServices);
+ } else {
+ Log.d(TAG, "BluetoothGatt is null");
+ }
+
+ } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+ Log.d(TAG, "Status BLE Disconnected");
+ setDisconnected(true);
+ setConnected(false);
+ }
+ }
+
+ public boolean isConnected() {
+ return isConnected;
+ }
+
+ @Override
+ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ super.onCharacteristicRead(gatt, characteristic, status);
+ Log.i("CharacteristicRead", characteristic.toString());
+
+ }
+
+ public void setConnected(boolean connected) {
+ isConnected = connected;
+ }
+
+ public boolean isDisconnected() {
+ return isDisconnected;
+ }
+
+ public void setDisconnected(boolean disconnected) {
+ isDisconnected = disconnected;
+ }
+
+ @Override
+ public void onCharacteristicChanged(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic) {
+ readChangedCharacteristic(characteristic);
+ }
+
+ public void readChangedCharacteristic(BluetoothGattCharacteristic characteristic) {
+ byte[] data;
+ data = characteristic.getValue(); // *** this is going to get overwritten by next call, so make a queue
+
+ if (data != null && data.length > 0 && (isConnected())) {
+ messageBuffer.append(new String(data, 0, data.length));
+
+ if(JsonStreamer.containsJson(messageBuffer.toString())) {
+ int delimiterIndex = messageBuffer.indexOf(DELIMITER);
+ if (delimiterIndex != -1) {
+ byte message[] = messageBuffer.substring(0, delimiterIndex + 1).getBytes();
+ BLEInputStream.getInstance().putDataInBuffer(message);
+ messageBuffer.delete(0, delimiterIndex + 1);
+ }
+ } else {
+ BLEInputStream.getInstance().putDataInBuffer(data);
+ }
+ }
+ }
+
+ @Override
+ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ BluetoothGattService gattService = gatt.getService(UUID.fromString(C5_OPENXC_BLE_SERVICE_UUID));
+ BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(UUID.fromString(C5_OPENXC_BLE_CHARACTERISTIC_NOTIFY_UUID));
+ gatt.setCharacteristicNotification(gattCharacteristic, true);
+ BluetoothGattDescriptor descriptor = gattCharacteristic.getDescriptor(UUID.fromString(C5_OPENXC_BLE_DESCRIPTOR_NOTIFY_UUID));
+ descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
+ gatt.writeDescriptor(descriptor);
+ }
+ }
+
+}
diff --git a/library/src/main/java/com/openxc/messages/Command.java b/library/src/main/java/com/openxc/messages/Command.java
index 91a6a000e..d48c7b8ef 100644
--- a/library/src/main/java/com/openxc/messages/Command.java
+++ b/library/src/main/java/com/openxc/messages/Command.java
@@ -1,34 +1,38 @@
package com.openxc.messages;
+import android.os.Parcel;
+
import com.google.common.base.Objects;
+import com.google.gson.annotations.SerializedName;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
-import android.os.Parcel;
-
import static com.google.common.base.MoreObjects.toStringHelper;
-import com.google.gson.annotations.SerializedName;
-
/**
* A Command message defined by the OpenXC message format.
- *
+ *
* Commands are keyed on the command name.
*/
public class Command extends KeyedMessage {
protected static final String COMMAND_KEY = "command";
protected static final String DIAGNOSTIC_REQUEST_KEY = "request";
protected static final String ACTION_KEY = "action";
-
+ protected static final String BUS_KEY = "bus";
+ protected static final String ENABLED_KEY = "enabled";
+ protected static final String BYPASS_KEY = "bypass";
+ protected static final String FORMAT_KEY = "format";
+ protected static final String UNIX_TIME_KEY = "unix_time";
public enum CommandType {
- VERSION, DEVICE_ID, DIAGNOSTIC_REQUEST, PLATFORM
+ VERSION, DEVICE_ID, DIAGNOSTIC_REQUEST, PLATFORM, PASSTHROUGH, AF_BYPASS, PAYLOAD_FORMAT
+ , SD_MOUNT_STATUS, RTC_CONFIGURATION
}
- private static final String[] sRequiredFieldsValues = new String[] {
- COMMAND_KEY };
+ private static final String[] sRequiredFieldsValues = new String[]{
+ COMMAND_KEY};
private static final Set sRequiredFields = new HashSet<>(
Arrays.asList(sRequiredFieldsValues));
@@ -41,6 +45,43 @@ public enum CommandType {
@SerializedName(DIAGNOSTIC_REQUEST_KEY)
private DiagnosticRequest mDiagnosticRequest;
+ @SerializedName(BUS_KEY)
+ private int mBus;
+
+ @SerializedName(ENABLED_KEY)
+ private boolean mEnabled;
+
+ @SerializedName(BYPASS_KEY)
+ private boolean mBypass;
+
+ @SerializedName(FORMAT_KEY)
+ private String mFormat;
+
+ @SerializedName(UNIX_TIME_KEY)
+ private long mUnixTime;
+
+ public Command(CommandType command, int bus, boolean enabled) {
+ mCommand = command;
+ mBus = bus;
+ mEnabled = enabled;
+ }
+
+ public Command(CommandType command, boolean bypass, int bus) {
+ mCommand = command;
+ mBus = bus;
+ mBypass = bypass;
+ }
+
+ public Command(String format,CommandType command) {
+ mFormat = format;
+ mCommand = command;
+ }
+
+ public Command(CommandType command, long unixTime) {
+ this.mCommand = command;
+ this.mUnixTime = unixTime;
+ }
+
public Command(CommandType command, String action) {
mCommand = command;
mAction = action;
@@ -71,9 +112,49 @@ public DiagnosticRequest getDiagnosticRequest() {
return mDiagnosticRequest;
}
+ public int getBus() {
+ return mBus;
+ }
+
+ public void setBus(int mBus) {
+ this.mBus = mBus;
+ }
+
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.mEnabled = enabled;
+ }
+
+ public boolean isBypass() {
+ return mBypass;
+ }
+
+ public void setBypass(boolean bypass) {
+ this.mBypass = bypass;
+ }
+
+ public String getFormat() {
+ return mFormat;
+ }
+
+ public void setFormat(String Format) {
+ this.mFormat = Format;
+ }
+
+ public long getUnixTime() {
+ return mUnixTime;
+ }
+
+ public void setUnixTime(long unixTime) {
+ this.mUnixTime = unixTime;
+ }
+
@Override
public MessageKey getKey() {
- if(super.getKey() == null) {
+ if (super.getKey() == null) {
HashMap key = new HashMap<>();
key.put(COMMAND_KEY, getCommand());
setKey(new MessageKey(key));
@@ -87,7 +168,7 @@ public static boolean containsRequiredFields(Set fields) {
@Override
public boolean equals(Object obj) {
- if(!super.equals(obj) || !(obj instanceof Command)) {
+ if (!super.equals(obj) || !(obj instanceof Command)) {
return false;
}
@@ -95,18 +176,28 @@ public boolean equals(Object obj) {
return Objects.equal(getCommand(), other.getCommand()) &&
Objects.equal(getDiagnosticRequest(),
other.getDiagnosticRequest()) &&
- Objects.equal(getAction(), other.getAction());
+ Objects.equal(getAction(), other.getAction()) &&
+ Objects.equal(getBus(), other.getBus()) &&
+ Objects.equal(isEnabled(), other.isEnabled()) &&
+ Objects.equal(isBypass(), other.isBypass()) &&
+ Objects.equal(getFormat(), other.getFormat()) &&
+ Objects.equal(getUnixTime(), other.getUnixTime());
}
@Override
public String toString() {
return toStringHelper(this)
- .add("timestamp", getTimestamp())
- .add("command", getCommand())
- .add("action", getAction())
- .add("diagnostic_request", getDiagnosticRequest())
- .add("extras", getExtras())
- .toString();
+ .add("timestamp", getTimestamp())
+ .add("command", getCommand())
+ .add("bus", getBus())
+ .add("enabled", isEnabled())
+ .add("bypass", isBypass())
+ .add("format", getFormat())
+ .add("unix_time",getUnixTime())
+ .add("action", getAction())
+ .add("diagnostic_request", getDiagnosticRequest())
+ .add("extras", getExtras())
+ .toString();
}
@Override
@@ -115,6 +206,11 @@ public void writeToParcel(Parcel out, int flags) {
out.writeSerializable(getCommand());
out.writeString(getAction());
out.writeParcelable(getDiagnosticRequest(), flags);
+ out.writeInt(getBus());
+ out.writeByte((byte) (isEnabled() ? 1 : 0));
+ out.writeByte((byte) (isBypass() ? 1 : 0));
+ out.writeString(getFormat());
+ out.writeLong(getUnixTime());
}
@Override
@@ -123,11 +219,17 @@ protected void readFromParcel(Parcel in) {
mCommand = (CommandType) in.readSerializable();
mAction = in.readString();
mDiagnosticRequest = in.readParcelable(DiagnosticRequest.class.getClassLoader());
+ mBus = in.readInt();
+ mBypass = in.readByte() != 0;
+ mEnabled = in.readByte() != 0;
+ mFormat = in.readString();
+ mUnixTime = in.readLong();
}
protected Command(Parcel in) {
readFromParcel(in);
}
- protected Command() { }
+ protected Command() {
+ }
}
diff --git a/library/src/main/java/com/openxc/messages/CustomCommand.java b/library/src/main/java/com/openxc/messages/CustomCommand.java
new file mode 100644
index 000000000..1927ea396
--- /dev/null
+++ b/library/src/main/java/com/openxc/messages/CustomCommand.java
@@ -0,0 +1,92 @@
+package com.openxc.messages;
+
+import android.os.Parcel;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * A Custom Command message based on the OpenXC message format.
+ * Commands are keyed on the command name.
+ */
+public class CustomCommand extends KeyedMessage {
+ protected static final String COMMAND_KEY = "command";
+
+ private HashMap commands = new HashMap<>();
+
+ public CustomCommand(HashMap commands) {
+ this.commands = commands;
+ }
+
+ public HashMap getCommands() {
+ return commands;
+ }
+
+ @Override
+ public MessageKey getKey() {
+ if (super.getKey() == null) {
+ HashMap key = new HashMap<>();
+ key.put(COMMAND_KEY, commands.get(COMMAND_KEY));
+ setKey(new MessageKey(key));
+ }
+ return super.getKey();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!super.equals(obj) || !(obj instanceof CustomCommand)) {
+ return false;
+ }
+
+ final CustomCommand other = (CustomCommand) obj;
+ return Objects.equal(getCommands(), other.getCommands());
+ }
+
+ @Override
+ public String toString() {
+ MoreObjects.ToStringHelper finalString = toStringHelper(COMMAND_KEY);
+ finalString.add("timestamp", getTimestamp());
+ for (Map.Entry entry : commands.entrySet()) {
+ finalString.add(entry.getKey(), entry.getValue());
+ }
+
+ return finalString.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ final int N = commands.size();
+ out.writeInt(N);
+ if (N > 0) {
+ for (Map.Entry entry : commands.entrySet()) {
+ out.writeString(entry.getKey());
+ String dat = entry.getValue();
+ out.writeString(dat);
+ }
+ }
+ }
+
+ @Override
+ protected void readFromParcel(Parcel in) {
+ super.readFromParcel(in);
+ final int N = in.readInt();
+ for (int i = 0; i < N; i++) {
+ String key = in.readString();
+ String value = in.readString();
+ commands.put(key, value);
+ }
+ }
+
+ protected CustomCommand(Parcel in) {
+ readFromParcel(in);
+ }
+
+ protected CustomCommand() {
+ }
+}
diff --git a/library/src/main/java/com/openxc/messages/CustomCommandResponse.java b/library/src/main/java/com/openxc/messages/CustomCommandResponse.java
new file mode 100644
index 000000000..17fcd79db
--- /dev/null
+++ b/library/src/main/java/com/openxc/messages/CustomCommandResponse.java
@@ -0,0 +1,114 @@
+package com.openxc.messages;
+
+import android.os.Parcel;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A response to a Custom Command from the vehicle interface.
+ *
+ * Custom Command responses have the same key as the original custom command request.
+ *
+ * Only difference between custom command response and command response is type of command.
+ */
+public class CustomCommandResponse extends KeyedMessage {
+
+ private static final String COMMAND_RESPONSE_KEY = "command_response";
+ private static final String STATUS_KEY = "status";
+ private static final String MESSAGE_KEY = "message";
+
+ private static final String[] sRequiredFieldsValues = new String[] {
+ COMMAND_RESPONSE_KEY, STATUS_KEY };
+ private static final Set sRequiredFields = new HashSet<>(
+ Arrays.asList(sRequiredFieldsValues));
+
+ @SerializedName(COMMAND_RESPONSE_KEY)
+ private String command;
+
+ @SerializedName(STATUS_KEY)
+ private boolean status;
+
+ // Message is optional
+ @SerializedName(MESSAGE_KEY)
+ private String message;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String getCommand() {
+ return command;
+ }
+ public void setCommand(String mCommand) {
+ this.command = mCommand;
+ }
+ public boolean getStatus() {
+ return status;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(!super.equals(obj) || !(obj instanceof CustomCommandResponse)) {
+ return false;
+ }
+
+ final CustomCommandResponse other = (CustomCommandResponse) obj;
+ return Objects.equal(command, other.command) &&
+ Objects.equal(message, other.message) &&
+ Objects.equal(status, other.status);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("timestamp", getTimestamp())
+ .add("command", getCommand())
+ .add("status", getStatus())
+ .add("message", getMessage())
+ .add("extras", getExtras())
+ .toString();
+ }
+
+ @Override
+ public MessageKey getKey() {
+ if(super.getKey() == null) {
+ HashMap key = new HashMap<>();
+ key.put(Command.COMMAND_KEY, getCommand());
+ setKey(new MessageKey(key));
+ }
+ return super.getKey();
+ }
+
+ public static boolean containsRequiredFields(Set fields) {
+ return fields.containsAll(sRequiredFields);
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeString(getCommand());
+ out.writeInt(getStatus() ? 1 : 0);
+ out.writeString(getMessage());
+ }
+
+ @Override
+ protected void readFromParcel(Parcel in) {
+ super.readFromParcel(in);
+ command = in.readString();
+ status = in.readInt() == 1;
+ message = in.readString();
+ }
+
+ protected CustomCommandResponse(Parcel in) {
+ readFromParcel(in);
+ }
+
+ protected CustomCommandResponse() { }
+}
diff --git a/library/src/main/java/com/openxc/messages/formatters/CustomCommandSerializer.java b/library/src/main/java/com/openxc/messages/formatters/CustomCommandSerializer.java
new file mode 100644
index 000000000..3312c49ab
--- /dev/null
+++ b/library/src/main/java/com/openxc/messages/formatters/CustomCommandSerializer.java
@@ -0,0 +1,34 @@
+package com.openxc.messages.formatters;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.openxc.messages.CustomCommand;
+
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+
+public class CustomCommandSerializer implements JsonSerializer {
+ /***
+ * A custom serializer for Custom Command. The custom commands are received in
+ * HashMap and then each key value is mapped as separate properties rather than a single
+ * JsonArray. This allows us to add any number of custom commands and then send it in openxc
+ * standard message format.
+ * @param customCommand
+ * @param typeOfSrc
+ * @param context
+ * @return
+ */
+ @Override
+ public JsonElement serialize
+ (CustomCommand customCommand, Type typeOfSrc, JsonSerializationContext context) {
+ JsonObject jObject = new JsonObject();
+ HashMap commands = customCommand.getCommands();
+ for (Map.Entry entry : commands.entrySet()) {
+ jObject.addProperty(entry.getKey(),entry.getValue());
+ }
+ return jObject;
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/openxc/messages/formatters/JsonFormatter.java b/library/src/main/java/com/openxc/messages/formatters/JsonFormatter.java
index affdec1d0..6510f81df 100644
--- a/library/src/main/java/com/openxc/messages/formatters/JsonFormatter.java
+++ b/library/src/main/java/com/openxc/messages/formatters/JsonFormatter.java
@@ -1,24 +1,19 @@
package com.openxc.messages.formatters;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.math.BigDecimal;
-import java.lang.reflect.Type;
-
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import com.google.gson.JsonSyntaxException;
-import com.google.gson.JsonSerializer;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import com.google.gson.JsonSyntaxException;
import com.openxc.messages.CanMessage;
import com.openxc.messages.Command;
import com.openxc.messages.CommandResponse;
+import com.openxc.messages.CustomCommand;
+import com.openxc.messages.CustomCommandResponse;
import com.openxc.messages.DiagnosticResponse;
import com.openxc.messages.EventedSimpleVehicleMessage;
import com.openxc.messages.NamedVehicleMessage;
@@ -26,6 +21,13 @@
import com.openxc.messages.UnrecognizedMessageTypeException;
import com.openxc.messages.VehicleMessage;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
/**
* A formatter for serializing and deserializing JSON OpenXC messages.
*/
@@ -43,6 +45,7 @@ public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonS
return new JsonPrimitive(value);
}
});
+ builder.registerTypeAdapter(CustomCommand.class, new CustomCommandSerializer());
sGson = builder.create();
}
@@ -92,27 +95,38 @@ public static VehicleMessage deserialize(String data)
for(Map.Entry entry : root.entrySet()) {
fields.add(entry.getKey());
}
-
VehicleMessage message;
- if(CanMessage.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, CanMessage.class);
- } else if(DiagnosticResponse.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, DiagnosticResponse.class);
- } else if(Command.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, Command.class);
- } else if(CommandResponse.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, CommandResponse.class);
- } else if(EventedSimpleVehicleMessage.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, EventedSimpleVehicleMessage.class);
- } else if(SimpleVehicleMessage.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, SimpleVehicleMessage.class);
- } else if(NamedVehicleMessage.containsRequiredFields(fields)) {
- message = sGson.fromJson(root, NamedVehicleMessage.class);
- } else if(fields.contains(VehicleMessage.EXTRAS_KEY)) {
- message = sGson.fromJson(root, VehicleMessage.class);
- } else {
- throw new UnrecognizedMessageTypeException(
- "Unrecognized combination of fields: " + fields);
+ try {
+ if (CanMessage.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, CanMessage.class);
+ } else if (DiagnosticResponse.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, DiagnosticResponse.class);
+ } else if (Command.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, Command.class);
+ } else if (CommandResponse.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, CommandResponse.class);
+ if (((CommandResponse) message).getCommand() == null) {
+ /* Both CommandResponse and CustomCommandResponse have exact fields but different
+ keys. If Command(key) for CommandResponse can not be de-serialized then it
+ must be a CustomCommandResponse.
+ */
+ message = sGson.fromJson(root, CustomCommandResponse.class);
+ }
+ } else if (EventedSimpleVehicleMessage.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, EventedSimpleVehicleMessage.class);
+ } else if (SimpleVehicleMessage.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, SimpleVehicleMessage.class);
+ } else if (NamedVehicleMessage.containsRequiredFields(fields)) {
+ message = sGson.fromJson(root, NamedVehicleMessage.class);
+ } else if (fields.contains(VehicleMessage.EXTRAS_KEY)) {
+ message = sGson.fromJson(root, VehicleMessage.class);
+ } else {
+ throw new UnrecognizedMessageTypeException(
+ "Unrecognized combination of fields: " + fields);
+ }
+ }catch (NumberFormatException e){
+ throw new UnrecognizedMessageTypeException(
+ "Unable to parse JSON from \"" + data + "\": " + e);
}
return message;
}
diff --git a/library/src/main/java/com/openxc/messages/formatters/binary/BinaryDeserializer.java b/library/src/main/java/com/openxc/messages/formatters/binary/BinaryDeserializer.java
index e91163593..21f58e89d 100644
--- a/library/src/main/java/com/openxc/messages/formatters/binary/BinaryDeserializer.java
+++ b/library/src/main/java/com/openxc/messages/formatters/binary/BinaryDeserializer.java
@@ -159,6 +159,18 @@ private static Command deserializeCommand(
commandType = CommandType.VERSION;
} else if(serializedType.equals(BinaryMessages.ControlCommand.Type.DEVICE_ID)) {
commandType = CommandType.DEVICE_ID;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PLATFORM)) {
+ commandType = CommandType.PLATFORM;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PASSTHROUGH)) {
+ commandType = CommandType.PASSTHROUGH;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.ACCEPTANCE_FILTER_BYPASS)) {
+ commandType = CommandType.AF_BYPASS;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PAYLOAD_FORMAT)) {
+ commandType = CommandType.PAYLOAD_FORMAT;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.SD_MOUNT_STATUS)) {
+ commandType = CommandType.SD_MOUNT_STATUS;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.RTC_CONFIGURATION)) {
+ commandType = CommandType.RTC_CONFIGURATION;
} else if(serializedType.equals(BinaryMessages.ControlCommand.Type.DIAGNOSTIC)) {
commandType = CommandType.DIAGNOSTIC_REQUEST;
} else {
@@ -228,6 +240,18 @@ private static CommandResponse deserializeCommandResponse(
commandType = CommandType.VERSION;
} else if(serializedType.equals(BinaryMessages.ControlCommand.Type.DEVICE_ID)) {
commandType = CommandType.DEVICE_ID;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PLATFORM)){
+ commandType = CommandType.PLATFORM;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PASSTHROUGH)){
+ commandType = CommandType.PASSTHROUGH;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.ACCEPTANCE_FILTER_BYPASS)){
+ commandType = CommandType.AF_BYPASS;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.PAYLOAD_FORMAT)){
+ commandType = CommandType.PAYLOAD_FORMAT;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.SD_MOUNT_STATUS)){
+ commandType = CommandType.SD_MOUNT_STATUS;
+ } else if(serializedType.equals(BinaryMessages.ControlCommand.Type.RTC_CONFIGURATION)){
+ commandType = CommandType.RTC_CONFIGURATION;
} else if(serializedType.equals(BinaryMessages.ControlCommand.Type.DIAGNOSTIC)) {
commandType = CommandType.DIAGNOSTIC_REQUEST;
} else {
diff --git a/library/src/main/java/com/openxc/messages/formatters/binary/BinarySerializer.java b/library/src/main/java/com/openxc/messages/formatters/binary/BinarySerializer.java
index 3c62b0571..2b5c53754 100644
--- a/library/src/main/java/com/openxc/messages/formatters/binary/BinarySerializer.java
+++ b/library/src/main/java/com/openxc/messages/formatters/binary/BinarySerializer.java
@@ -135,10 +135,22 @@ private static void serializeCommand(BinaryMessages.VehicleMessage.Builder build
BinaryMessages.ControlCommand.Builder messageBuilder =
BinaryMessages.ControlCommand.newBuilder();
CommandType commandType = message.getCommand();
- if(commandType.equals(CommandType.VERSION)) {
+ if (commandType.equals(CommandType.VERSION)) {
messageBuilder.setType(BinaryMessages.ControlCommand.Type.VERSION);
- } else if(commandType.equals(CommandType.DEVICE_ID)) {
+ } else if (commandType.equals(CommandType.DEVICE_ID)) {
messageBuilder.setType(BinaryMessages.ControlCommand.Type.DEVICE_ID);
+ } else if(commandType.equals(CommandType.PLATFORM)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PLATFORM);
+ } else if(commandType.equals(CommandType.PASSTHROUGH)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PASSTHROUGH);
+ } else if(commandType.equals(CommandType.AF_BYPASS)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.ACCEPTANCE_FILTER_BYPASS);
+ } else if(commandType.equals(CommandType.PAYLOAD_FORMAT)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PAYLOAD_FORMAT);
+ } else if(commandType.equals(CommandType.SD_MOUNT_STATUS)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.SD_MOUNT_STATUS);
+ } else if(commandType.equals(CommandType.RTC_CONFIGURATION)){
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.RTC_CONFIGURATION);
} else if(commandType.equals(CommandType.DIAGNOSTIC_REQUEST)) {
messageBuilder.setType(BinaryMessages.ControlCommand.Type.DIAGNOSTIC);
messageBuilder.setDiagnosticRequest(
@@ -161,6 +173,18 @@ private static void serializeCommandResponse(BinaryMessages.VehicleMessage.Build
messageBuilder.setType(BinaryMessages.ControlCommand.Type.VERSION);
} else if(message.getCommand().equals(CommandType.DEVICE_ID)) {
messageBuilder.setType(BinaryMessages.ControlCommand.Type.DEVICE_ID);
+ } else if(message.getCommand().equals(CommandType.PLATFORM)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PLATFORM);
+ } else if(message.getCommand().equals(CommandType.PASSTHROUGH)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PASSTHROUGH);
+ } else if(message.getCommand().equals(CommandType.AF_BYPASS)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.ACCEPTANCE_FILTER_BYPASS);
+ } else if(message.getCommand().equals(CommandType.PAYLOAD_FORMAT)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.PAYLOAD_FORMAT);
+ } else if(message.getCommand().equals(CommandType.SD_MOUNT_STATUS)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.SD_MOUNT_STATUS);
+ } else if(message.getCommand().equals(CommandType.RTC_CONFIGURATION)) {
+ messageBuilder.setType(BinaryMessages.ControlCommand.Type.RTC_CONFIGURATION);
} else if(message.getCommand().equals(CommandType.DIAGNOSTIC_REQUEST)) {
messageBuilder.setType(BinaryMessages.ControlCommand.Type.DIAGNOSTIC);
} else {
diff --git a/library/src/main/java/com/openxc/remote/VehicleService.java b/library/src/main/java/com/openxc/remote/VehicleService.java
index 4dea97a56..af04403e1 100644
--- a/library/src/main/java/com/openxc/remote/VehicleService.java
+++ b/library/src/main/java/com/openxc/remote/VehicleService.java
@@ -1,8 +1,11 @@
package com.openxc.remote;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
+import android.os.Build;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -24,7 +27,6 @@
import com.openxc.sources.NativeLocationSource;
import com.openxc.sources.VehicleDataSource;
import com.openxc.sources.WakeLockManager;
-
import com.openxcplatform.R;
/**
@@ -53,6 +55,7 @@ public class VehicleService extends Service implements DataPipeline.Operator {
private final static String TAG = "VehicleService";
private final static int SERVICE_NOTIFICATION_ID = 1000;
+ private static final String CHANNEL_ID = "OpenXC Notification Channel";
// Work around an issue with instrumentation tests and foreground services
// https://code.google.com/p/android/issues/detail?id=12122
@@ -62,6 +65,7 @@ public class VehicleService extends Service implements DataPipeline.Operator {
private DataPipeline mPipeline = new DataPipeline(this);
private ApplicationSource mApplicationSource = new ApplicationSource();
private VehicleDataSource mNativeLocationSource;
+ private VehicleDataSource mPhoneSensorSource;
private VehicleInterface mVehicleInterface;
private RemoteCallbackSink mNotifier = new RemoteCallbackSink();
private WakeLockManager mWakeLocker;
@@ -103,6 +107,19 @@ public IBinder onBind(Intent intent) {
private void moveToForeground() {
if(!mForeground) {
Log.i(TAG, "Moving service to foreground.");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ // Create the NotificationChannel
+ CharSequence name = getString(R.string.channel_name);
+ String description = getString(R.string.channel_description);
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
+ mChannel.setDescription(description);
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ NotificationManager notificationManager = (NotificationManager) getSystemService(
+ NOTIFICATION_SERVICE);
+ notificationManager.createNotificationChannel(mChannel);
+ }
try {
// I'd like to not have to depend on the EnablerActivity, but
@@ -116,7 +133,7 @@ private void moveToForeground() {
this, 0, intent, 0);
NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this);
+ new NotificationCompat.Builder(this, CHANNEL_ID);
notificationBuilder.setContentTitle(getString(R.string.openxc_name))
.setContentInfo(getString(R.string.notification_content))
.setSmallIcon(R.drawable.openxc_notification_icon_small_white)
diff --git a/library/src/main/java/com/openxc/sinks/DweetSink.java b/library/src/main/java/com/openxc/sinks/DweetSink.java
new file mode 100644
index 000000000..30d5c8f2a
--- /dev/null
+++ b/library/src/main/java/com/openxc/sinks/DweetSink.java
@@ -0,0 +1,157 @@
+package com.openxc.sinks;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.buglabs.dweetlib.DweetLib;
+import com.openxc.messages.VehicleMessage;
+import com.openxc.messages.formatters.JsonFormatter;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+/**
+ * Sends bundles of all incoming vehicle data to Dweet.io.
+ *
+ *
+ */
+public class DweetSink extends ContextualVehicleDataSink {
+ private final static String TAG = "DweetSink";
+ private final static int UPLOAD_BATCH_SIZE = 25;
+ private final static int MAXIMUM_QUEUED_RECORDS = 1000;
+ private final static int HTTP_TIMEOUT = 5000;
+
+ private String mThingName;
+ private Context mContext;
+ private BlockingQueue mRecordQueue =
+ new LinkedBlockingQueue<>(MAXIMUM_QUEUED_RECORDS);
+ private Lock mQueueLock = new ReentrantLock();
+ private Condition mRecordsQueued = mQueueLock.newCondition();
+ private DweetThread mDweeter = new DweetThread();
+
+ /**
+ * Initialize and start a new DweetSink immediately.
+ *
+ * @param thing_name the Thing Name to send Dweets to with the JSON data.
+ */
+ public DweetSink(Context context, String thing_name) {
+ super(context);
+ mThingName = thing_name;
+ mContext = context;
+ }
+
+ @Override
+ public void stop() {
+ mDweeter.done();
+ }
+
+ @Override
+ public void receive(VehicleMessage message) {
+ mRecordQueue.offer(message);
+ if(mRecordQueue.size() >= UPLOAD_BATCH_SIZE) {
+ try {
+ mQueueLock.lock();
+ mRecordsQueued.signal();
+ } finally {
+ mQueueLock.unlock();
+ }
+ }
+ }
+
+ private static class UploaderException extends DataSinkException {
+ private static final long serialVersionUID = 7436279598279767619L;
+
+ public UploaderException() { }
+
+ public UploaderException(String message) {
+ super(message);
+ }
+ }
+
+ private class DweetThread extends Thread {
+ private boolean mRunning = true;
+ ArrayList records ;
+ private Handler dweetHandler;
+
+ public DweetThread() {
+ start();
+ dweetHandler = new Handler(Looper.getMainLooper());
+ dweetHandler.postDelayed(runnable, 1000);
+ }
+
+ @Override
+ public void run() {
+ while(mRunning) {
+ try {
+ records = getRecords();
+ } catch(InterruptedException e) {
+ Log.w(TAG, "Dweeter was interrupted", e);
+ break;
+ }
+ }
+ }
+
+ public void done() {
+ mRunning = false;
+ }
+
+ private ArrayList getRecords() throws InterruptedException {
+ try {
+ mQueueLock.lock();
+ while(mRecordQueue.isEmpty()) {
+ // the queue is already thread safe, but we use this lock to get
+ // a condition variable we can use to signal when a batch has
+ // been queued.
+ mRecordsQueued.await(5, TimeUnit.SECONDS);
+ }
+
+ ArrayList records = new ArrayList<>();
+ mRecordQueue.drainTo(records, UPLOAD_BATCH_SIZE);
+ return records;
+ } finally {
+ mQueueLock.unlock();
+ }
+ }
+ private Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ if(mRunning) {
+ DweetLib.DweetCallback cb = new DweetLib.DweetCallback() {
+ @Override
+ public void callback(ArrayList