Skip to content

Commit

Permalink
Merge pull request #1773 from Apres2707/atom_support
Browse files Browse the repository at this point in the history
add atom support
  • Loading branch information
jamorham authored Oct 4, 2021
2 parents 727aeaf + 378e645 commit 49817a5
Show file tree
Hide file tree
Showing 7 changed files with 437 additions and 4 deletions.
181 changes: 181 additions & 0 deletions app/src/main/java/com/eveningoutpost/dexdrip/Models/Atom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package com.eveningoutpost.dexdrip.Models;

import com.eveningoutpost.dexdrip.ImportedLibraries.usbserial.util.HexDump;
import com.eveningoutpost.dexdrip.Models.UserError.Log;
import com.eveningoutpost.dexdrip.NFCReaderX;
import com.eveningoutpost.dexdrip.R;
import com.eveningoutpost.dexdrip.UtilityModels.BridgeResponse;
import com.eveningoutpost.dexdrip.UtilityModels.Constants;
import com.eveningoutpost.dexdrip.UtilityModels.LibreUtils;
import com.eveningoutpost.dexdrip.UtilityModels.PersistentStore;
import com.eveningoutpost.dexdrip.UtilityModels.Pref;

import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;

import static com.eveningoutpost.dexdrip.xdrip.gs;

/**
*
*/

public class Atom {
private static final String TAG = "Atom";//?????"Atom";

private static volatile byte[] s_full_data = null;
private static volatile int s_acumulatedSize = 0;

public static boolean isAtom() {
final ActiveBluetoothDevice activeBluetoothDevice = ActiveBluetoothDevice.first();
if (activeBluetoothDevice == null || activeBluetoothDevice.name == null) {
return false;
}
return activeBluetoothDevice.name.contentEquals("Atom");
}


public static BridgeResponse getAtomResponse() {
final BridgeResponse reply = new BridgeResponse();
ByteBuffer ackMessage = ByteBuffer.allocate(6);
ackMessage.put(0, (byte) 0x02);
ackMessage.put(1, (byte) 0x01);
ackMessage.put(2, (byte) 0x00);
ackMessage.put(3, (byte) 0x00);
ackMessage.put(4, (byte) 0x00);
ackMessage.put(5, (byte) 0x2B);
reply.add(ackMessage);
return reply;
}

public static int lens = 344;
public static int ATOM_FOOTER = 8;

static int errorCount = 0;


static byte[] patchUid = null;
static byte[] patchInfo = null;

public static BridgeResponse decodeAtomPacket(byte[] buffer, int len) {
final BridgeResponse reply = new BridgeResponse();
int first = 0xff & buffer[0];
if (first == 0x80) {
PersistentStore.setString("Atombattery", Integer.toString(buffer[4]));
Pref.setInt("bridge_battery", buffer[4]);
String atomfirmware = buffer[2] + "." + buffer[3];
String atomHArdware = buffer[buffer.length-2] + "." + buffer[buffer.length-1];
PersistentStore.setString("AtomHArdware", atomHArdware);
PersistentStore.setString("AtomFirmware", atomfirmware);
ByteBuffer ackMessage = ByteBuffer.allocate(6);
ackMessage.put(0, (byte) 0x02);
ackMessage.put(1, (byte) 0x01);
ackMessage.put(2, (byte) 0x00);
ackMessage.put(3, (byte) 0x00);
ackMessage.put(4, (byte) 0x00);
ackMessage.put(5, (byte) 0x2B);
reply.add(ackMessage);
s_full_data = null;
return getAtomResponse();
}
if (first == 0xC0) {
patchUid = Arrays.copyOfRange(buffer, 2, 10);
String SensorSn = LibreUtils.decodeSerialNumberKey(patchUid);
PersistentStore.setString("LibreSN", SensorSn);

if (SensorSanity.checkLibreSensorChangeIfEnabled(SensorSn)) {
Log.e(TAG, "Problem with Libre Serial Number - not processing");
}

return reply;
}
if (first == 0xC1) {
double fv = JoH.tolerantParseDouble(PersistentStore.getString("AtomFirmware"));
if (fv < 1.35) {
patchInfo = Arrays.copyOfRange(buffer, 3, 9);
} else {
if (buffer.length >= 11) {
patchInfo = Arrays.copyOfRange(buffer, 5, 11);
}
}
return reply;
}
if (first == 0x82) {
int expectedSize = lens + ATOM_FOOTER;
if (s_full_data == null) {
InitBuffer(expectedSize);
}
addData(buffer);
return reply;

}

if (first == 0xBF) {
Log.e(TAG, "No sensor has been found");
reply.setError_message(gs(R.string.no_sensor_found));
s_full_data = null;
errorCount++;
if (errorCount <= 2) {
return getAtomResponse();
}
return reply;
}


return reply;
}


static void addData(byte[] buffer) {
System.arraycopy(buffer, 4, s_full_data, s_acumulatedSize, buffer.length-4);
s_acumulatedSize = s_acumulatedSize + buffer.length - 4;
AreWeDone();
}


static void AreWeDone() {
if (s_acumulatedSize < lens) {
return;
}
long now = JoH.tsl();
String SensorSn = PersistentStore.getString("LibreSN");


byte[] data = Arrays.copyOfRange(s_full_data, 0, Constants.LIBRE_1_2_FRAM_SIZE);

// Set the time of the current reading
PersistentStore.setLong("libre-reading-timestamp", JoH.tsl());

boolean checksum_ok = NFCReaderX.HandleGoodReading(SensorSn, data, now, true, patchUid, patchInfo);
int expectedSize = lens + ATOM_FOOTER;
InitBuffer(expectedSize);
errorCount = 0;
Log.e(TAG, "We have all the data that we need " + s_acumulatedSize + " checksum_ok = " + checksum_ok + HexDump.dumpHexString(data));

}


static void InitBuffer(int expectedSize) {
s_full_data = new byte[expectedSize];
s_acumulatedSize = 0;
}

public static ArrayList<ByteBuffer> initialize() {
Log.e(TAG, "initialize!");
Pref.setInt("bridge_battery", 0); //force battery to no-value before first reading
return resetAtomState();
}

private static ArrayList<ByteBuffer> resetAtomState() {
ArrayList<ByteBuffer> ret = new ArrayList<>();

// Make Atom send data every 5 minutes
ByteBuffer ackMessage = ByteBuffer.allocate(3);
ackMessage.put(0, (byte) 0x00);
ackMessage.put(1, (byte) 0x01);
ackMessage.put(2, (byte) 0x05);
ret.add(ackMessage);
return ret;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ class ExtendedLibreBlock {
@Expose
public int Bubblebattery;
@Expose
public int Atombattery;
@Expose
public int nfc_sensor_age;
@Expose
public LibreBlock libreBlock;
Expand All @@ -263,6 +265,7 @@ public String toExtendedJson() {
elb.bridge_battery = Pref.getInt("bridge_battery", 0);
elb.Tomatobattery = PersistentStore.getStringToInt("Tomatobattery", 0);
elb.Bubblebattery = PersistentStore.getStringToInt("Bubblebattery", 0);
elb.Atombattery = PersistentStore.getStringToInt("Atombattery", 0);
elb.nfc_sensor_age = Pref.getInt("nfc_sensor_age", 0);
elb.libreBlock = this;
return JoH.defaultGsonInstance().toJson(elb);
Expand All @@ -284,6 +287,7 @@ public static LibreBlock createFromExtendedJson(String json) {
Pref.setInt("bridge_battery", elb.bridge_battery);
PersistentStore.setString("Tomatobattery", Integer.toString(elb.Tomatobattery));
PersistentStore.setString("Bubblebattery", Integer.toString(elb.Bubblebattery));
PersistentStore.setString("Atombattery", Integer.toString(elb.Atombattery));
Pref.setInt("nfc_sensor_age", elb.nfc_sensor_age);
return elb.libreBlock;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.eveningoutpost.dexdrip.Home;
import com.eveningoutpost.dexdrip.ImportedLibraries.usbserial.util.HexDump;
import com.eveningoutpost.dexdrip.Models.ActiveBluetoothDevice;
import com.eveningoutpost.dexdrip.Models.Atom;
import com.eveningoutpost.dexdrip.Models.BgReading;
import com.eveningoutpost.dexdrip.Models.Bubble;
import com.eveningoutpost.dexdrip.Models.JoH;
Expand Down Expand Up @@ -405,7 +406,7 @@ public synchronized void onServicesDiscovered(BluetoothGatt gatt, int status) {

final BluetoothGattService gattService = mBluetoothGatt.getService(xDripDataService);
if (gattService == null) {
if (!(static_use_blukon || blueReader.isblueReader() || Tomato.isTomato()||Bubble.isBubble() || LibreBluetooth.isLibreBluettoh())) {
if (!(static_use_blukon || blueReader.isblueReader() || Tomato.isTomato()||Bubble.isBubble()||Atom.isAtom() || LibreBluetooth.isLibreBluettoh())) {
Log.w(TAG, "onServicesDiscovered: xdrip service " + xDripDataService + " not found"); //TODO the selection of nrf is not active at the beginning,so this error will be trown one time unneeded, mey to be optimized.
// TODO this should be reworked to be an efficient selector
listAvailableServices(mBluetoothGatt);
Expand Down Expand Up @@ -533,6 +534,22 @@ public void run() {
}
});

servicesDiscovered = DISCOVERED.NULL; // reset this state
}else if (Atom.isAtom()) {
status("Enabled atom");
Log.d(TAG, "Queueing atom initialization..");
Inevitable.task("initialize-atom", 4000, new Runnable() {
@Override
public void run() {
final List<ByteBuffer> buffers = Atom.initialize();
for (ByteBuffer buffer : buffers) {
sendBtMessage(buffer);
JoH.threadSleep(150);
}
Log.d(TAG, "atom initialized and data requested");
}
});

servicesDiscovered = DISCOVERED.NULL; // reset this state
}
}
Expand Down Expand Up @@ -901,6 +918,8 @@ public static String getBestLimitterHardwareName() {
return xdrip.getAppContext().getString(R.string.tomato);
} else if (static_use_nrf && Bubble.isBubble()) {
return xdrip.getAppContext().getString(R.string.bubble);
}else if (static_use_nrf && Atom.isAtom()) {
return xdrip.getAppContext().getString(R.string.atom);
} else if (static_use_blukon) {
return xdrip.getAppContext().getString(R.string.blukon);
} else if (static_use_transmiter_pl_bluetooth) {
Expand Down Expand Up @@ -1099,7 +1118,12 @@ public void run() {
l.add(new StatusItem("Bubble Firmware", PersistentStore.getString("BubbleFirmware")));
l.add(new StatusItem("Libre SN", PersistentStore.getString("LibreSN")));
}

if (Atom.isAtom()) {
l.add(new StatusItem("Atom Battery", PersistentStore.getString("Atombattery")));
l.add(new StatusItem("Atom Hardware", PersistentStore.getString("AtomHArdware")));
l.add(new StatusItem("Atom Firmware", PersistentStore.getString("AtomFirmware")));
l.add(new StatusItem("Libre SN", PersistentStore.getString("LibreSN")));
}
if (static_use_blukon) {
l.add(new StatusItem("Battery", Pref.getInt("bridge_battery", 0) + "%"));
l.add(new StatusItem("Sensor age", JoH.qs(((double) Pref.getInt("nfc_sensor_age", 0)) / 1440, 1) + "d"));
Expand Down Expand Up @@ -1719,6 +1743,19 @@ public synchronized void setSerialDataToTransmitterRawData(byte[] buffer, int le
}
gotValidPacket();

}else if (Atom.isAtom()) {
final BridgeResponse reply = Atom.decodeAtomPacket(buffer, len);
if (reply.shouldDelay()) {
Inevitable.task("send-atom-reply", reply.getDelay(), () -> sendReply(reply));
} else {
sendReply(reply);
}
if (reply.hasError()) {
JoH.static_toast_long(reply.getError_message());
error(reply.getError_message());
}
gotValidPacket();

} else if (LibreBluetooth.isLibreBluettoh()) {
final BridgeResponse reply = LibreBluetooth.decodeLibrePacket(buffer, len);
if (reply.shouldDelay()) {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@
<string name="blukon">BluCon</string>
<string name="tomato">Tomato</string>
<string name="bubble">Bubble</string>
<string name="atom">Atom</string>
<string name="use_gravity_sensor_to_rotate_items">Use Gravity Sensor to rotate items</string>
<string name="low_bridge_battery">Low bridge battery</string>
<string name="reminders">Reminders</string>
Expand Down
Loading

0 comments on commit 49817a5

Please sign in to comment.