Skip to content

Commit

Permalink
add SetModes
Browse files Browse the repository at this point in the history
  • Loading branch information
jwoglom committed Mar 31, 2024
1 parent 1023b56 commit 3d1a7a9
Show file tree
Hide file tree
Showing 5 changed files with 357 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@
import com.jwoglom.pumpx2.pump.messages.response.currentStatus.UnknownMobiOpcodeNeg66Response;
import com.jwoglom.pumpx2.pump.messages.request.currentStatus.UnknownMobiOpcodeNeg124Request;
import com.jwoglom.pumpx2.pump.messages.response.currentStatus.UnknownMobiOpcodeNeg124Response;
import com.jwoglom.pumpx2.pump.messages.request.control.SetModesRequest;
import com.jwoglom.pumpx2.pump.messages.response.control.SetModesResponse;
// IMPORT_END
import com.jwoglom.pumpx2.shared.L;

Expand Down Expand Up @@ -223,6 +225,7 @@ public enum Messages {
UNKNOWN_MOBI_OPCODE110(UnknownMobiOpcode110Request.class, UnknownMobiOpcode110Response.class),
UNKNOWN_MOBI_OPCODE_NEG66(UnknownMobiOpcodeNeg66Request.class, UnknownMobiOpcodeNeg66Response.class),
UNKNOWN_MOBI_OPCODE_NEG124(UnknownMobiOpcodeNeg124Request.class, UnknownMobiOpcodeNeg124Response.class),
SET_MODES(SetModesRequest.class, SetModesResponse.class),
// MESSAGES_END
;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.jwoglom.pumpx2.pump.messages.request.control;

import com.google.common.base.Preconditions;
import com.jwoglom.pumpx2.pump.messages.bluetooth.Characteristic;
import com.jwoglom.pumpx2.pump.messages.helpers.Bytes;
import com.jwoglom.pumpx2.pump.messages.Message;
import com.jwoglom.pumpx2.pump.messages.MessageType;
import com.jwoglom.pumpx2.pump.messages.annotations.MessageProps;
import com.jwoglom.pumpx2.pump.messages.models.KnownApiVersion;
import com.jwoglom.pumpx2.pump.messages.models.SupportedDevices;
import com.jwoglom.pumpx2.pump.messages.response.control.SetModesResponse;

@MessageProps(
opCode=-52,
size=1,
type=MessageType.REQUEST,
characteristic=Characteristic.CONTROL,
signed=true,
minApi=KnownApiVersion.MOBI_API_V3_5,
supportedDevices=SupportedDevices.MOBI_ONLY,
response=SetModesResponse.class
)
public class SetModesRequest extends Message {
private int bitmap;

public SetModesRequest() {}

public SetModesRequest(int bitmap) {
parse(buildCargo(bitmap));
}

public SetModesRequest(ModeCommand mode) {
this(mode.getBitmap());
}

public SetModesRequest(byte[] raw) {
this.cargo = raw;
this.bitmap = raw[0];
}

public void parse(byte[] raw) {
raw = this.removeSignedRequestHmacBytes(raw);
Preconditions.checkArgument(raw.length == props().size(), "got "+raw.length);
this.cargo = raw;
this.bitmap = raw[0];
}


public static byte[] buildCargo(int bitmap) {
return Bytes.combine(
// 10 at 0
new byte[]{(byte) bitmap}
);
}

public int getBitmap() {
return bitmap;
}

public ModeCommand getCommand() {
return ModeCommand.fromBitmap(bitmap);
}

public enum ModeCommand {
SLEEP_MODE_ON(1),
SLEEP_MODE_OFF(2),
EXERCISE_MODE_ON(3),
EXERCISE_MODE_OFF(4),
;

private int bitmap;
ModeCommand(int bitmap) {
this.bitmap = bitmap;
}

public int getBitmap() {
return bitmap;
}

public static ModeCommand fromBitmap(int bitmap) {
for (ModeCommand c : values()) {
if (c.getBitmap() == bitmap) {
return c;
}
}
return null;
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.jwoglom.pumpx2.pump.messages.response.control;

import com.google.common.base.Preconditions;
import com.jwoglom.pumpx2.pump.messages.bluetooth.Characteristic;
import com.jwoglom.pumpx2.pump.messages.helpers.Bytes;
import com.jwoglom.pumpx2.pump.messages.Message;
import com.jwoglom.pumpx2.pump.messages.MessageType;
import com.jwoglom.pumpx2.pump.messages.annotations.MessageProps;
import com.jwoglom.pumpx2.pump.messages.models.KnownApiVersion;
import com.jwoglom.pumpx2.pump.messages.models.SupportedDevices;
import com.jwoglom.pumpx2.pump.messages.request.control.SetModesRequest;

import java.math.BigInteger;

@MessageProps(
opCode=-51,
size=1,
type=MessageType.RESPONSE,
characteristic=Characteristic.CONTROL,
signed=true,
minApi=KnownApiVersion.MOBI_API_V3_5,
supportedDevices=SupportedDevices.MOBI_ONLY,
request=SetModesRequest.class
)
public class SetModesResponse extends Message {

private int status;

public SetModesResponse() {}

public SetModesResponse(int status) {
this.cargo = buildCargo(status);
}

public SetModesResponse(byte[] raw) {
parse(raw);
}

public void parse(byte[] raw) {
raw = this.removeSignedRequestHmacBytes(raw);
Preconditions.checkArgument(raw.length == props().size());
this.cargo = raw;
this.status = raw[0];

}


public static byte[] buildCargo(int status) {
return Bytes.combine(
new byte[]{(byte) status});
}

public int getStatus() {
return status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.jwoglom.pumpx2.pump.messages.request.control;

import static com.jwoglom.pumpx2.pump.messages.MessageTester.assertHexEquals;
import static com.jwoglom.pumpx2.pump.messages.MessageTester.initPumpState;

import static org.junit.Assert.assertEquals;

import com.jwoglom.pumpx2.pump.messages.MessageTester;
import com.jwoglom.pumpx2.pump.messages.PacketArrayList;
import com.jwoglom.pumpx2.pump.messages.bluetooth.CharacteristicUUID;

import org.apache.commons.codec.DecoderException;
import org.junit.Test;

public class SetModesRequestTest {
@Test
public void testSetModesRequest_exerciseModeOffToOn() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);
// empty cargo
SetModesRequest expected = new SetModesRequest(new byte[]{3});

SetModesRequest parsedReq = (SetModesRequest) MessageTester.test(
// Untitled_2_Live_-_Humans_iPhone - 2024-03-28T00:18:39.016000+00:00
"0179cc7919034d978b1e32c70c65d5b530fdf45a",
121,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected,
"0079b59d63358bab1b849bb1a4e4"
); // resp: 0079cd791900e8428b1ec8fa29dc63d8f79a1c678b339ba801061a620659e904

assertHexEquals(expected.getCargo(), parsedReq.getCargo());
assertEquals(3, parsedReq.getBitmap());
assertEquals(SetModesRequest.ModeCommand.EXERCISE_MODE_ON, parsedReq.getCommand());
}

@Test
public void testSetModesRequest_exerciseModeOnToOff() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);
// empty cargo
SetModesRequest expected = new SetModesRequest(new byte[]{4});

SetModesRequest parsedReq = (SetModesRequest) MessageTester.test(
// Untitled_2_Live_-_Humans_iPhone - 2024-03-28T00:18:58.516000+00:00
"0181cc81190461978b1eff1bb7778cd232419aa1",
-127,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected,
"0081d97936364e86562320d973e2"
); // resp: 0081cd811900fb428b1ec6956c4b467290f8ba7ee8df78dd2ca119dbef422894

assertHexEquals(expected.getCargo(), parsedReq.getCargo());
assertEquals(4, parsedReq.getBitmap());
assertEquals(SetModesRequest.ModeCommand.EXERCISE_MODE_OFF, parsedReq.getCommand());
}

@Test
public void testSetModesRequest_sleepModeOffToOn() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);
// empty cargo
SetModesRequest expected = new SetModesRequest(new byte[]{1});

SetModesRequest parsedReq = (SetModesRequest) MessageTester.test(
// Untitled_2_Live_-_Humans_iPhone - 2024-03-28T00:19:26.068000+00:00
"018acc8a19017d978b1ef95a55180db9a2f1c821",
-118,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected,
"008ace22b462fab923c16c2cc428"
); // resp: 008acd8a190017438b1e16af1181440210dc1feed9fc36a3882124bc7bd2678e

assertHexEquals(expected.getCargo(), parsedReq.getCargo());
assertEquals(1, parsedReq.getBitmap());
assertEquals(SetModesRequest.ModeCommand.SLEEP_MODE_ON, parsedReq.getCommand());
}


@Test
public void testSetModesRequest_sleepModeOnToOff() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);
// empty cargo
SetModesRequest expected = new SetModesRequest(new byte[]{2});

SetModesRequest parsedReq = (SetModesRequest) MessageTester.test(
// Untitled_2_Live_-_Humans_iPhone - 2024-03-28T00:19:55.126000+00:00
"0191cc9119029a978b1e7ce08a7a68802cca71dc",
-111,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected,
"009134fd2877d2a8bd3247ef819d"
); // resp: 0091cd91190034438b1e5858889224eafe67bf93fc50bb2575a514602ff34e62

assertHexEquals(expected.getCargo(), parsedReq.getCargo());
assertEquals(2, parsedReq.getBitmap());
assertEquals(SetModesRequest.ModeCommand.SLEEP_MODE_OFF, parsedReq.getCommand());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.jwoglom.pumpx2.pump.messages.response.control;

import static com.jwoglom.pumpx2.pump.messages.MessageTester.assertHexEquals;
import static com.jwoglom.pumpx2.pump.messages.MessageTester.initPumpState;

import static org.junit.Assert.assertEquals;

import com.jwoglom.pumpx2.pump.messages.MessageTester;
import com.jwoglom.pumpx2.pump.messages.PacketArrayList;
import com.jwoglom.pumpx2.pump.messages.bluetooth.CharacteristicUUID;

import org.apache.commons.codec.DecoderException;
import org.junit.Test;

public class SetModesResponseTest {
@Test
public void testSetModesResponse_exerciseModeOffToOn() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);

SetModesResponse expected = new SetModesResponse(
// byte[] raw
new byte[]{0}
);

SetModesResponse parsedRes = (SetModesResponse) MessageTester.test(
"0079cd791900e8428b1ec8fa29dc63d8f79a1c678b339ba801061a620659e904",
121,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected
);

assertHexEquals(expected.getCargo(), parsedRes.getCargo());
assertEquals(0, parsedRes.getStatus());
}

@Test
public void testSetModesResponse_exerciseModeOnToOff() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);

SetModesResponse expected = new SetModesResponse(
// byte[] raw
new byte[]{0}
);

SetModesResponse parsedRes = (SetModesResponse) MessageTester.test(
"0081cd811900fb428b1ec6956c4b467290f8ba7ee8df78dd2ca119dbef422894",
-127,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected
);

assertHexEquals(expected.getCargo(), parsedRes.getCargo());
assertEquals(0, parsedRes.getStatus());
}

@Test
public void testSetModesResponse_sleepModeOffToOn() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);

SetModesResponse expected = new SetModesResponse(
// byte[] raw
new byte[]{0}
);

SetModesResponse parsedRes = (SetModesResponse) MessageTester.test(
"008acd8a190017438b1e16af1181440210dc1feed9fc36a3882124bc7bd2678e",
-118,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected
);

assertHexEquals(expected.getCargo(), parsedRes.getCargo());
assertEquals(0, parsedRes.getStatus());
}

@Test
public void testSetModesResponse_sleepModeOnToOff() throws DecoderException {
// TimeSinceResetResponse[currentTime=512443145,pumpTimeSinceReset=1905716,cargo={9,67,-117,30,52,20,29,0}]
initPumpState(PacketArrayList.IGNORE_INVALID_HMAC, 1905716L);

SetModesResponse expected = new SetModesResponse(
// byte[] raw
new byte[]{0}
);

SetModesResponse parsedRes = (SetModesResponse) MessageTester.test(
"0091cd91190034438b1e5858889224eafe67bf93fc50bb2575a514602ff34e62",
-111,
2,
CharacteristicUUID.CONTROL_CHARACTERISTICS,
expected
);

assertHexEquals(expected.getCargo(), parsedRes.getCargo());
assertEquals(0, parsedRes.getStatus());
}
}

0 comments on commit 3d1a7a9

Please sign in to comment.