forked from pires/obd-java-api
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added CommandAvailabilityHelper to allow easy checking of which comma…
…nds are available
- Loading branch information
Héctor Barreras Almarcha
committed
Oct 10, 2015
1 parent
e9d513a
commit 005cf36
Showing
3 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
148 changes: 148 additions & 0 deletions
148
src/main/java/com/github/pires/obd/utils/CommandAvailabilityHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package com.github.pires.obd.utils; | ||
|
||
public abstract class CommandAvailabilityHelper { | ||
|
||
/* | ||
All around this class, integers are used where unsigned bytes should be used. Too bad they don't exist in Java. | ||
Thank you Oracle. | ||
*/ | ||
|
||
/** | ||
* Digests the given string into an array of integers which can be used to check for command availability | ||
* | ||
* @param availabilityString An 8*n (where n is an integer) character string containing only numbers and uppercase letters from A to F | ||
* @return An integer array containing the digested information | ||
*/ | ||
public static int[] digestAvailabilityString(final String availabilityString) { | ||
//The string must have 8*n characters, n being an integer | ||
if (availabilityString.length() % 8 != 0) { | ||
throw new IllegalArgumentException("Invalid length for Availability String supplied: " + availabilityString); | ||
} | ||
|
||
//Each two characters of the string will be digested into one byte, thus the resulting array will | ||
//have half the elements the string has | ||
int[] availabilityArray = new int[availabilityString.length() / 2]; | ||
|
||
for (int i = 0, a = 0; i < availabilityArray.length; ++i, a += 2) { | ||
//First character is more significant | ||
availabilityArray[i] = 16 * parseHexChar(availabilityString.charAt(a)) + parseHexChar(availabilityString.charAt(a + 1)); | ||
} | ||
|
||
return availabilityArray; | ||
} | ||
|
||
private static int parseHexChar(char hexChar) { | ||
switch (hexChar) { | ||
case '0': | ||
return 0; | ||
|
||
case '1': | ||
return 1; | ||
|
||
case '2': | ||
return 2; | ||
|
||
case '3': | ||
return 3; | ||
|
||
case '4': | ||
return 4; | ||
|
||
case '5': | ||
return 5; | ||
|
||
case '6': | ||
return 6; | ||
|
||
case '7': | ||
return 7; | ||
|
||
case '8': | ||
return 8; | ||
|
||
case '9': | ||
return 9; | ||
|
||
case 'A': | ||
return 10; | ||
|
||
case 'B': | ||
return 11; | ||
|
||
case 'C': | ||
return 12; | ||
|
||
case 'D': | ||
return 13; | ||
|
||
case 'E': | ||
return 14; | ||
|
||
case 'F': | ||
return 15; | ||
|
||
default: | ||
throw new IllegalArgumentException("Invalid character [" + hexChar + "] supplied"); | ||
} | ||
} | ||
|
||
/** | ||
* Checks whether the command identified by commandPid is available, as noted by availabilityString. | ||
* <p/> | ||
* This is a direct call to {@link CommandAvailabilityHelper#isAvailable(String, int[])} with built-in String digestion | ||
*/ | ||
public static boolean isAvailable(final String commandPid, final String availabilityString) { | ||
return isAvailable(commandPid, digestAvailabilityString(availabilityString)); | ||
} | ||
|
||
/** | ||
* Checks whether the command identified by commandPid is available, as noted by availabilityArray | ||
*/ | ||
public static boolean isAvailable(final String commandPid, int[] availabilityArray) { | ||
//Which byte from the array contains the info we want? | ||
//Ignore first 3 characters from the command string, which are 2 for PID mode and 1 whitespace | ||
int cmdNumber = Integer.parseInt(commandPid, 16); | ||
int arrayIndex = cmdNumber / 8; | ||
|
||
if (arrayIndex > availabilityArray.length - 1) | ||
throw new IllegalArgumentException("availabilityArray does not contain enough entries to check for command " + commandPid); | ||
|
||
//Subtract 8 from cmdNumber until we have it in the 1-8 range | ||
while (cmdNumber > 8) { | ||
cmdNumber -= 8; | ||
} | ||
|
||
int requestedAvailability; | ||
|
||
switch (cmdNumber) { | ||
case 1: | ||
requestedAvailability = 128; | ||
break; | ||
case 2: | ||
requestedAvailability = 64; | ||
break; | ||
case 3: | ||
requestedAvailability = 32; | ||
break; | ||
case 4: | ||
requestedAvailability = 16; | ||
break; | ||
case 5: | ||
requestedAvailability = 8; | ||
break; | ||
case 6: | ||
requestedAvailability = 4; | ||
break; | ||
case 7: | ||
requestedAvailability = 2; | ||
break; | ||
case 8: | ||
requestedAvailability = 1; | ||
break; | ||
default: | ||
throw new RuntimeException("This is not supposed to happen."); | ||
} | ||
|
||
return requestedAvailability == (requestedAvailability & availabilityArray[arrayIndex]); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
src/test/java/com/github/pires/obd/utils/CommandAvailabilityHelperTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.github.pires.obd.utils; | ||
|
||
import com.github.pires.obd.commands.engine.ThrottlePositionCommand; | ||
import org.junit.Test; | ||
|
||
import static org.junit.Assert.*; | ||
|
||
public class CommandAvailabilityHelperTest { | ||
|
||
@Test | ||
public void testDigestAvailabilityString() throws Exception { | ||
|
||
String string = "BE1FA813"; | ||
int[] expResult = new int[]{Integer.parseInt("10111110", 2), Integer.parseInt("00011111", 2), | ||
Integer.parseInt("10101000", 2), Integer.parseInt("00010011", 2)}; | ||
int[] result = CommandAvailabilityHelper.digestAvailabilityString(string); | ||
assertArrayEquals(expResult, result); | ||
|
||
//Now with 16 characters | ||
string = "BE1FA813BE1FA813"; | ||
expResult = new int[]{Integer.parseInt("10111110", 2), Integer.parseInt("00011111", 2), | ||
Integer.parseInt("10101000", 2), Integer.parseInt("00010011", 2), | ||
Integer.parseInt("10111110", 2), Integer.parseInt("00011111", 2), | ||
Integer.parseInt("10101000", 2), Integer.parseInt("00010011", 2)}; | ||
|
||
result = CommandAvailabilityHelper.digestAvailabilityString(string); | ||
assertArrayEquals(expResult, result); | ||
|
||
try { | ||
CommandAvailabilityHelper.digestAvailabilityString("AAA"); | ||
fail("IllegalArgumentException should have been thrown but wasn't"); | ||
} catch (IllegalArgumentException e) { | ||
//test passed | ||
} | ||
|
||
try { | ||
CommandAvailabilityHelper.digestAvailabilityString("AAAAAAAR"); | ||
fail("IllegalArgumentException should have been thrown but wasn't"); | ||
} catch (IllegalArgumentException e) { | ||
//test passed | ||
} | ||
} | ||
|
||
@Test | ||
public void testIsAvailable() throws Exception { | ||
assertEquals(CommandAvailabilityHelper.isAvailable("02", "BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("07", "BE1FA813"), true); | ||
assertEquals(CommandAvailabilityHelper.isAvailable(new ThrottlePositionCommand().getCommandPID() /*11*/, "BE1FA813"), true); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("1A", "BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("1D", "BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("1F", "BE1FA813"), true); | ||
|
||
try { | ||
CommandAvailabilityHelper.isAvailable("2F", "BE1FA813"); | ||
fail("IllegalArgumentException should have been thrown but wasn't"); | ||
} catch (IllegalArgumentException e) { | ||
//test passed | ||
} | ||
|
||
assertEquals(CommandAvailabilityHelper.isAvailable("22", "BE1FA813BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("27", "BE1FA813BE1FA813"), true); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("3A", "BE1FA813BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("3D", "BE1FA813BE1FA813"), false); | ||
assertEquals(CommandAvailabilityHelper.isAvailable("3F", "BE1FA813BE1FA813"), true); | ||
} | ||
} |
The code doesn't build because of this.