Files
2020-07-18 21:44:27 -04:00

278 lines
13 KiB
Java

package com.eveningoutpost.dexdrip.Models;
import android.provider.BaseColumns;
import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
import com.activeandroid.query.Select;
import com.eveningoutpost.dexdrip.GcmActivity;
import com.eveningoutpost.dexdrip.Home;
import com.eveningoutpost.dexdrip.ImportedLibraries.usbserial.util.HexDump;
import com.eveningoutpost.dexdrip.Models.UserError.Log;
import com.eveningoutpost.dexdrip.UtilityModels.Constants;
import com.eveningoutpost.dexdrip.UtilityModels.Pref;
import com.eveningoutpost.dexdrip.utils.CheckBridgeBattery;
import com.eveningoutpost.dexdrip.utils.DexCollectionType;
import com.google.gson.annotations.Expose;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* Created by Emma Black on 11/6/14.
*/
@Table(name = "TransmitterData", id = BaseColumns._ID)
public class TransmitterData extends Model {
private final static String TAG = TransmitterData.class.getSimpleName();
@Expose
@Column(name = "timestamp", index = true)
public long timestamp;
// TODO these should be int or long surely
@Expose
@Column(name = "raw_data")
public double raw_data;
@Expose
@Column(name = "filtered_data")
public double filtered_data;
@Expose
@Column(name = "sensor_battery_level")
public int sensor_battery_level;
@Expose
@Column(name = "uuid", index = true)
public String uuid;
public static synchronized TransmitterData create(byte[] buffer, int len, Long timestamp) {
if (len < 6) {
return null;
}
final TransmitterData transmitterData = new TransmitterData();
try {
if ((buffer[0] == 0x11 || buffer[0] == 0x15) && buffer[1] == 0x00) {
//this is a dexbridge packet. Process accordingly.
Log.i(TAG, "create Processing a Dexbridge packet");
final ByteBuffer txData = ByteBuffer.allocate(len);
txData.order(ByteOrder.LITTLE_ENDIAN);
txData.put(buffer, 0, len);
transmitterData.raw_data = txData.getInt(2);
transmitterData.filtered_data = txData.getInt(6);
// bitwise and with 0xff (1111....1) to avoid that the byte is treated as signed.
transmitterData.sensor_battery_level = txData.get(10) & 0xff;
if (buffer[0] == 0x15) {
Log.i(TAG, "create Processing a Dexbridge packet includes delay information");
transmitterData.timestamp = timestamp - txData.getInt(16);
} else {
transmitterData.timestamp = timestamp;
}
Log.i(TAG, "Created transmitterData record with Raw value of " + transmitterData.raw_data + " and Filtered value of " + transmitterData.filtered_data + " at " + timestamp + " with timestamp " + transmitterData.timestamp);
} else { //this is NOT a dexbridge packet. Process accordingly.
Log.i(TAG, "create Processing a BTWixel or IPWixel packet");
StringBuilder data_string = new StringBuilder();
for (int i = 0; i < len; ++i) {
data_string.append((char) buffer[i]);
}
final String[] data = data_string.toString().split("\\s+");
if (data.length > 1) {
transmitterData.sensor_battery_level = Integer.parseInt(data[1]);
if (data.length > 2) {
try {
Pref.setInt("bridge_battery", Integer.parseInt(data[2]));
if (Home.get_master()) {
GcmActivity.sendBridgeBattery(Pref.getInt("bridge_battery", -1));
}
CheckBridgeBattery.checkBridgeBattery();
} catch (Exception e) {
Log.e(TAG, "Got exception processing classic wixel or limitter battery value: " + e.toString());
}
if (data.length > 3) {
if ((DexCollectionType.getDexCollectionType() == DexCollectionType.LimiTTer)
&& (!Pref.getBooleanDefaultFalse("use_transmiter_pl_bluetooth"))) {
try {
// reported sensor age in minutes
final Integer sensorAge = Integer.parseInt(data[3]);
if ((sensorAge > 0) && (sensorAge < 200000))
Pref.setInt("nfc_sensor_age", sensorAge);
} catch (Exception e) {
Log.e(TAG, "Got exception processing field 4 in classic limitter protocol: " + e);
}
}
}
}
}
transmitterData.raw_data = Integer.parseInt(data[0]);
transmitterData.filtered_data = Integer.parseInt(data[0]);
// TODO process does_have_filtered_here with extended protocol
transmitterData.timestamp = timestamp;
}
//Stop allowing readings that are older than the last one - or duplicate data, its bad! (from savek-cc)
final TransmitterData lastTransmitterData = TransmitterData.last();
if (lastTransmitterData != null && lastTransmitterData.timestamp >= transmitterData.timestamp) {
Log.e(TAG, "Rejecting TransmitterData constraint: last: " + JoH.dateTimeText(lastTransmitterData.timestamp) + " >= this: " + JoH.dateTimeText(transmitterData.timestamp));
return null;
}
if (lastTransmitterData != null && lastTransmitterData.raw_data == transmitterData.raw_data && Math.abs(lastTransmitterData.timestamp - transmitterData.timestamp) < (Constants.MINUTE_IN_MS * 2)) {
Log.e(TAG, "Rejecting identical TransmitterData constraint: last: " + JoH.dateTimeText(lastTransmitterData.timestamp) + " due to 2 minute rule this: " + JoH.dateTimeText(transmitterData.timestamp));
return null;
}
final Calibration lastCalibration = Calibration.lastValid();
if (lastCalibration != null && lastCalibration.timestamp > transmitterData.timestamp) {
Log.e(TAG, "Rejecting historical TransmitterData constraint: calib: " + JoH.dateTimeText(lastCalibration.timestamp) + " > this: " + JoH.dateTimeText(transmitterData.timestamp));
return null;
}
transmitterData.uuid = UUID.randomUUID().toString();
transmitterData.save();
return transmitterData;
} catch (Exception e) {
Log.e(TAG, "Got exception processing fields in protocol: " + e + " " + HexDump.dumpHexString(buffer));
}
return null;
}
public static synchronized TransmitterData create(int raw_data, int filtered_data, int sensor_battery_level, long timestamp) {
TransmitterData lastTransmitterData = TransmitterData.last();
if (lastTransmitterData != null && lastTransmitterData.raw_data == raw_data && Math.abs(lastTransmitterData.timestamp - new Date().getTime()) < (Constants.MINUTE_IN_MS * 2)) { //Stop allowing duplicate data, its bad!
return null;
}
TransmitterData transmitterData = new TransmitterData();
transmitterData.sensor_battery_level = sensor_battery_level;
transmitterData.raw_data = raw_data;
transmitterData.filtered_data = filtered_data;
transmitterData.timestamp = timestamp;
transmitterData.uuid = UUID.randomUUID().toString();
transmitterData.save();
return transmitterData;
}
public static synchronized TransmitterData create(int raw_data ,int sensor_battery_level, long timestamp) {
TransmitterData lastTransmitterData = TransmitterData.last();
if (lastTransmitterData != null && lastTransmitterData.raw_data == raw_data && Math.abs(lastTransmitterData.timestamp - new Date().getTime()) < (Constants.MINUTE_IN_MS * 2)) { //Stop allowing duplicate data, its bad!
return null;
}
TransmitterData transmitterData = new TransmitterData();
transmitterData.sensor_battery_level = sensor_battery_level;
transmitterData.raw_data = raw_data ;
transmitterData.timestamp = timestamp;
transmitterData.uuid = UUID.randomUUID().toString();
transmitterData.save();
return transmitterData;
}
public static TransmitterData last() {
return new Select()
.from(TransmitterData.class)
.orderBy("_ID desc")
.executeSingle();
}
public static List<TransmitterData> last(int count) {
return new Select()
.from(TransmitterData.class)
.orderBy("_ID desc")
.limit(count)
.execute();
}
public static TransmitterData lastByTimestamp() {
return new Select()
.from(TransmitterData.class)
.orderBy("timestamp desc")
.executeSingle();
}
public static TransmitterData getForTimestamp(double timestamp) {//KS
try {
Sensor sensor = Sensor.currentSensor();
if (sensor != null) {
TransmitterData bgReading = new Select()
.from(TransmitterData.class)
.where("timestamp <= ?", (timestamp + (60 * 1000))) // 1 minute padding (should never be that far off, but why not)
.orderBy("timestamp desc")
.executeSingle();
if (bgReading != null && Math.abs(bgReading.timestamp - timestamp) < (3 * 60 * 1000)) { //cool, so was it actually within 4 minutes of that bg reading?
Log.i(TAG, "getForTimestamp: Found a BG timestamp match");
return bgReading;
}
}
} catch (Exception e) {
Log.e(TAG,"getForTimestamp() Got exception on Select : "+e.toString());
return null;
}
Log.d(TAG, "getForTimestamp: No luck finding a BG timestamp match");
return null;
}
public static TransmitterData findByUuid(String uuid) {//KS
try {
return new Select()
.from(TransmitterData.class)
.where("uuid = ?", uuid)
.executeSingle();
} catch (Exception e) {
Log.e(TAG,"findByUuid() Got exception on Select : "+e.toString());
return null;
}
}
public static TransmitterData byid(long id) {
return new Select()
.from(TransmitterData.class)
.where("_ID = ?", id)
.executeSingle();
}
public static void updateTransmitterBatteryFromSync(final int battery_level) {
try {
TransmitterData td = TransmitterData.last();
if ((td == null) || (td.raw_data!=0))
{
td=TransmitterData.create(0,battery_level,(long)JoH.ts());
Log.d(TAG,"Created new fake transmitter data record for battery sync");
if (td==null) return;
}
if ((battery_level != td.sensor_battery_level) || ((JoH.ts()-td.timestamp)>(1000*60*60))) {
td.sensor_battery_level = battery_level;
td.timestamp = (long)JoH.ts(); // freshen timestamp on this bogus record for system status
Log.d(TAG,"Saving synced sensor battery, new level: "+battery_level);
td.save();
} else {
Log.d(TAG,"Synced sensor battery level same as existing: "+battery_level);
}
} catch (Exception e) {
Log.e(TAG,"Got exception updating sensor battery from sync: "+e.toString());
}
}
private static double roundRaw(TransmitterData td) {
return JoH.roundDouble(td.raw_data,3);
}
private static double roundFiltered(TransmitterData td) {
return JoH.roundDouble(td.filtered_data,3);
}
public static boolean unchangedRaw() {
final List<TransmitterData> items = last(3);
if (items != null && items.size() == 3) {
return (roundRaw(items.get(0)) == roundRaw(items.get(1))
&& roundRaw(items.get(0)) == roundRaw(items.get(2))
&& roundFiltered(items.get(0)) == roundFiltered(items.get(1))
&& roundFiltered(items.get(0)) == roundFiltered(items.get(2)));
}
return false;
}
}