mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-03 17:02:13 +01:00
WIP: Bip GPS fetching, parsing, exporting
Also adjust Mi2 date/time sending wrt DST offsets
This commit is contained in:
parent
eac8f5f8c7
commit
f5318287c4
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package nodomain.freeyourgadget.gadgetbridge.daogen;
|
package nodomain.freeyourgadget.gadgetbridge.daogen;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import de.greenrobot.daogenerator.DaoGenerator;
|
import de.greenrobot.daogenerator.DaoGenerator;
|
||||||
import de.greenrobot.daogenerator.Entity;
|
import de.greenrobot.daogenerator.Entity;
|
||||||
import de.greenrobot.daogenerator.Index;
|
import de.greenrobot.daogenerator.Index;
|
||||||
@ -32,6 +34,7 @@ public class GBDaoGenerator {
|
|||||||
private static final String MAIN_PACKAGE = "nodomain.freeyourgadget.gadgetbridge";
|
private static final String MAIN_PACKAGE = "nodomain.freeyourgadget.gadgetbridge";
|
||||||
private static final String MODEL_PACKAGE = MAIN_PACKAGE + ".model";
|
private static final String MODEL_PACKAGE = MAIN_PACKAGE + ".model";
|
||||||
private static final String VALID_BY_DATE = MODEL_PACKAGE + ".ValidByDate";
|
private static final String VALID_BY_DATE = MODEL_PACKAGE + ".ValidByDate";
|
||||||
|
private static final String ACTIVITY_SUMMARY = MODEL_PACKAGE + ".ActivitySummary";
|
||||||
private static final String OVERRIDE = "@Override";
|
private static final String OVERRIDE = "@Override";
|
||||||
private static final String SAMPLE_RAW_INTENSITY = "rawIntensity";
|
private static final String SAMPLE_RAW_INTENSITY = "rawIntensity";
|
||||||
private static final String SAMPLE_STEPS = "steps";
|
private static final String SAMPLE_STEPS = "steps";
|
||||||
@ -68,6 +71,8 @@ public class GBDaoGenerator {
|
|||||||
|
|
||||||
addCalendarSyncState(schema, device);
|
addCalendarSyncState(schema, device);
|
||||||
|
|
||||||
|
addBipActivitySummary(schema, user, device);
|
||||||
|
|
||||||
new DaoGenerator().generateAll(schema, "app/src/main/java");
|
new DaoGenerator().generateAll(schema, "app/src/main/java");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +302,31 @@ public class GBDaoGenerator {
|
|||||||
calendarSyncState.addIntProperty("hash").notNull();
|
calendarSyncState.addIntProperty("hash").notNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addBipActivitySummary(Schema schema, Entity user, Entity device) {
|
||||||
|
Entity summary = addEntity(schema, "BaseActivitySummary");
|
||||||
|
summary.implementsInterface(ACTIVITY_SUMMARY);
|
||||||
|
summary.addIdProperty();
|
||||||
|
|
||||||
|
summary.setJavaDoc(
|
||||||
|
"This class represents the summary of a user's activity event. I.e. a walk, hike, a bicycle tour, etc.");
|
||||||
|
|
||||||
|
summary.addStringProperty("name").codeBeforeGetter(OVERRIDE);
|
||||||
|
summary.addDateProperty("startTime").notNull().codeBeforeGetter(OVERRIDE);
|
||||||
|
summary.addDateProperty("endTime").notNull().codeBeforeGetter(OVERRIDE);
|
||||||
|
summary.addIntProperty("activityKind").notNull().codeBeforeGetter(OVERRIDE);
|
||||||
|
|
||||||
|
summary.addIntProperty("baseLongitude").javaDocGetterAndSetter("Temporary, bip-specific");
|
||||||
|
summary.addIntProperty("baseLatitude").javaDocGetterAndSetter("Temporary, bip-specific");
|
||||||
|
summary.addIntProperty("baseAltitude").javaDocGetterAndSetter("Temporary, bip-specific");
|
||||||
|
|
||||||
|
summary.addStringProperty("gpxTrack").codeBeforeGetter(OVERRIDE);
|
||||||
|
|
||||||
|
Property deviceId = summary.addLongProperty("deviceId").notNull().codeBeforeGetter(OVERRIDE).getProperty();
|
||||||
|
summary.addToOne(device, deviceId);
|
||||||
|
Property userId = summary.addLongProperty("userId").notNull().codeBeforeGetter(OVERRIDE).getProperty();
|
||||||
|
summary.addToOne(user, userId);
|
||||||
|
}
|
||||||
|
|
||||||
private static Property findProperty(Entity entity, String propertyName) {
|
private static Property findProperty(Entity entity, String propertyName) {
|
||||||
for (Property prop : entity.getProperties()) {
|
for (Property prop : entity.getProperties()) {
|
||||||
if (propertyName.equals(prop.getPropertyName())) {
|
if (propertyName.equals(prop.getPropertyName())) {
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
android:name=".devices.miband.MiBandPreferencesActivity"
|
android:name=".devices.miband.MiBandPreferencesActivity"
|
||||||
android:label="@string/preferences_miband_settings"
|
android:label="@string/preferences_miband_settings"
|
||||||
android:parentActivityName=".activities.SettingsActivity" />
|
android:parentActivityName=".activities.SettingsActivity" />
|
||||||
|
<activity
|
||||||
|
android:name=".activities.ActivitySummariesActivity"
|
||||||
|
android:label="@string/activity_summaries"
|
||||||
|
android:parentActivityName=".activities.ControlCenterv2" />
|
||||||
<activity
|
<activity
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:name=".activities.appmanager.AppManagerActivity"
|
android:name=".activities.appmanager.AppManagerActivity"
|
||||||
@ -401,7 +405,7 @@
|
|||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/screenshot_provider_paths"/>
|
android:resource="@xml/shared_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<receiver android:name=".SleepAlarmWidget">
|
<receiver android:name=".SleepAlarmWidget">
|
||||||
|
@ -24,6 +24,9 @@ import android.app.NotificationManager.Policy;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -591,4 +594,24 @@ public class GBApplication extends Application {
|
|||||||
public static Locale getLanguage() {
|
public static Locale getLanguage() {
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
try {
|
||||||
|
return getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA).versionName;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
GB.log("Unable to determine Gadgetbridge's version", GB.WARN, e);
|
||||||
|
return "0.0.0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNameAndVersion() {
|
||||||
|
try {
|
||||||
|
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
|
||||||
|
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_META_DATA);
|
||||||
|
return String.format("%s %s", appInfo.name, packageInfo.versionName);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
GB.log("Unable to determine Gadgetbridge's name/version", GB.WARN, e);
|
||||||
|
return "Gadgetbridge";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +148,7 @@ public abstract class Logging {
|
|||||||
}
|
}
|
||||||
StringBuilder builder = new StringBuilder(bytes.length * 5);
|
StringBuilder builder = new StringBuilder(bytes.length * 5);
|
||||||
for (byte b : bytes) {
|
for (byte b : bytes) {
|
||||||
builder.append(String.format("0x%2x", b));
|
builder.append(String.format("0x%02x", b));
|
||||||
builder.append(" ");
|
builder.append(" ");
|
||||||
}
|
}
|
||||||
return builder.toString().trim();
|
return builder.toString().trim();
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.adapter.AbstractItemAdapter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.adapter.ItemWithDetailsAdapter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
|
public abstract class AbstractListActivity<T> extends AbstractGBActivity {
|
||||||
|
private AbstractItemAdapter<T> itemAdapter;
|
||||||
|
private ListView itemListView;
|
||||||
|
|
||||||
|
public void setItemAdapter(AbstractItemAdapter<T> itemAdapter) {
|
||||||
|
this.itemAdapter = itemAdapter;
|
||||||
|
itemListView.setAdapter(itemAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void refresh() {
|
||||||
|
this.itemAdapter.loadItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractItemAdapter<T> getItemAdapter() {
|
||||||
|
return itemAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListView getItemListView() {
|
||||||
|
return itemListView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_list);
|
||||||
|
itemListView = (ListView) findViewById(R.id.itemListView);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.ContextMenu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.adapter.ActivitySummariesAdapter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
|
public class ActivitySummariesActivity extends AbstractListActivity<BaseActivitySummary> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setItemAdapter(new ActivitySummariesAdapter(this));
|
||||||
|
|
||||||
|
getItemListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
Object item = getItemAdapter().getItem(position);
|
||||||
|
if (item != null) {
|
||||||
|
ActivitySummary summary = (ActivitySummary) item;
|
||||||
|
String gpxTrack = summary.getGpxTrack();
|
||||||
|
if (gpxTrack != null) {
|
||||||
|
showTrack(gpxTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
getItemListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View v, final ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
MenuItem delete = menu.add("Delete");
|
||||||
|
delete.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
|
deleteItemAt(info.position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
getItemListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
return getItemListView().showContextMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteItemAt(int position) {
|
||||||
|
BaseActivitySummary item = getItemAdapter().getItem(position);
|
||||||
|
if (item != null) {
|
||||||
|
item.delete();
|
||||||
|
getItemAdapter().remove(item);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showTrack(String gpxTrack) {
|
||||||
|
try {
|
||||||
|
AndroidUtils.viewFile(gpxTrack, Intent.ACTION_VIEW, this);
|
||||||
|
} catch (IOException e) {
|
||||||
|
GB.toast(this, "Unable to display GPX track: " + e.getMessage(), Toast.LENGTH_LONG, GB.ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,122 @@
|
|||||||
|
/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||||
|
|
||||||
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Gadgetbridge is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.DrawableRes;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for displaying generic ItemWithDetails instances.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractItemAdapter<T> extends ArrayAdapter<T> {
|
||||||
|
|
||||||
|
public static final int SIZE_SMALL = 1;
|
||||||
|
public static final int SIZE_MEDIUM = 2;
|
||||||
|
public static final int SIZE_LARGE = 3;
|
||||||
|
private final Context context;
|
||||||
|
private final List<T> items;
|
||||||
|
private boolean horizontalAlignment;
|
||||||
|
private int size = SIZE_MEDIUM;
|
||||||
|
|
||||||
|
public AbstractItemAdapter(Context context) {
|
||||||
|
this (context, new ArrayList<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractItemAdapter(Context context, List<T> items) {
|
||||||
|
super(context, 0, items);
|
||||||
|
|
||||||
|
this.context = context;
|
||||||
|
this.items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHorizontalAlignment(boolean horizontalAlignment) {
|
||||||
|
this.horizontalAlignment = horizontalAlignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View view, ViewGroup parent) {
|
||||||
|
T item = getItem(position);
|
||||||
|
|
||||||
|
if (view == null) {
|
||||||
|
LayoutInflater inflater = (LayoutInflater) context
|
||||||
|
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
|
||||||
|
if (horizontalAlignment) {
|
||||||
|
view = inflater.inflate(R.layout.item_with_details_horizontal, parent, false);
|
||||||
|
} else {
|
||||||
|
switch (size) {
|
||||||
|
case SIZE_SMALL:
|
||||||
|
view = inflater.inflate(R.layout.item_with_details_small, parent, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
view = inflater.inflate(R.layout.item_with_details, parent, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImageView iconView = (ImageView) view.findViewById(R.id.item_image);
|
||||||
|
TextView nameView = (TextView) view.findViewById(R.id.item_name);
|
||||||
|
TextView detailsView = (TextView) view.findViewById(R.id.item_details);
|
||||||
|
|
||||||
|
nameView.setText(getName(item));
|
||||||
|
detailsView.setText(getDetails(item));
|
||||||
|
iconView.setImageResource(getIcon(item));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String getName(T item);
|
||||||
|
|
||||||
|
protected abstract String getDetails(T item);
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
protected abstract int getIcon(T item);
|
||||||
|
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getItems() {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadItems() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItems(List<T> items, boolean notify) {
|
||||||
|
this.items.clear();
|
||||||
|
this.items.addAll(items);
|
||||||
|
if (notify) {
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
|
public class ActivitySummariesAdapter extends AbstractItemAdapter<BaseActivitySummary> {
|
||||||
|
public ActivitySummariesAdapter(Context context) {
|
||||||
|
super(context);
|
||||||
|
loadItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadItems() {
|
||||||
|
try (DBHandler handler = GBApplication.acquireDB()) {
|
||||||
|
BaseActivitySummaryDao summaryDao = handler.getDaoSession().getBaseActivitySummaryDao();
|
||||||
|
List<BaseActivitySummary> allSummaries = summaryDao.loadAll();
|
||||||
|
setItems(allSummaries, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
GB.toast("Error loading activity summaries.", Toast.LENGTH_SHORT, GB.ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getName(BaseActivitySummary item) {
|
||||||
|
String name = item.getName();
|
||||||
|
if (name != null && name.length() > 0) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Date startTime = item.getStartTime();
|
||||||
|
if (startTime != null) {
|
||||||
|
return DateTimeUtils.formatDateTime(startTime);
|
||||||
|
}
|
||||||
|
return "Unknown activity";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDetails(BaseActivitySummary item) {
|
||||||
|
return ActivityKind.asString(item.getActivityKind(), getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getIcon(BaseActivitySummary item) {
|
||||||
|
return ActivityKind.getIconId(item.getActivityKind());
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.ActivitySummariesActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
|
import nodomain.freeyourgadget.gadgetbridge.activities.ConfigureAlarms;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.VibrationActivity;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
|
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
|
||||||
@ -210,6 +211,20 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//show activity tracks
|
||||||
|
holder.showActivityTracks.setVisibility(coordinator.supportsActivityTracks() ? View.VISIBLE : View.GONE);
|
||||||
|
holder.showActivityTracks.setOnClickListener(new View.OnClickListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent startIntent;
|
||||||
|
startIntent = new Intent(context, ActivitySummariesActivity.class);
|
||||||
|
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
|
||||||
|
context.startActivity(startIntent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
ItemWithDetailsAdapter infoAdapter = new ItemWithDetailsAdapter(context, device.getDeviceInfos());
|
ItemWithDetailsAdapter infoAdapter = new ItemWithDetailsAdapter(context, device.getDeviceInfos());
|
||||||
infoAdapter.setHorizontalAlignment(true);
|
infoAdapter.setHorizontalAlignment(true);
|
||||||
holder.deviceInfoList.setAdapter(infoAdapter);
|
holder.deviceInfoList.setAdapter(infoAdapter);
|
||||||
@ -338,6 +353,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
|||||||
ImageView manageAppsView;
|
ImageView manageAppsView;
|
||||||
ImageView setAlarmsView;
|
ImageView setAlarmsView;
|
||||||
ImageView showActivityGraphs;
|
ImageView showActivityGraphs;
|
||||||
|
ImageView showActivityTracks;
|
||||||
|
|
||||||
ImageView deviceInfoView;
|
ImageView deviceInfoView;
|
||||||
//overflow
|
//overflow
|
||||||
@ -365,6 +381,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter<GBDeviceAdapterv2.Vi
|
|||||||
manageAppsView = (ImageView) view.findViewById(R.id.device_action_manage_apps);
|
manageAppsView = (ImageView) view.findViewById(R.id.device_action_manage_apps);
|
||||||
setAlarmsView = (ImageView) view.findViewById(R.id.device_action_set_alarms);
|
setAlarmsView = (ImageView) view.findViewById(R.id.device_action_set_alarms);
|
||||||
showActivityGraphs = (ImageView) view.findViewById(R.id.device_action_show_activity_graphs);
|
showActivityGraphs = (ImageView) view.findViewById(R.id.device_action_show_activity_graphs);
|
||||||
|
showActivityTracks = (ImageView) view.findViewById(R.id.device_action_show_activity_tracks);
|
||||||
deviceInfoView = (ImageView) view.findViewById(R.id.device_info_image);
|
deviceInfoView = (ImageView) view.findViewById(R.id.device_info_image);
|
||||||
|
|
||||||
deviceInfoBox = (RelativeLayout) view.findViewById(R.id.device_item_infos_box);
|
deviceInfoBox = (RelativeLayout) view.findViewById(R.id.device_item_infos_box);
|
||||||
|
@ -17,77 +17,33 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
package nodomain.freeyourgadget.gadgetbridge.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
|
import nodomain.freeyourgadget.gadgetbridge.model.ItemWithDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for displaying generic ItemWithDetails instances.
|
* Adapter for displaying generic ItemWithDetails instances.
|
||||||
*/
|
*/
|
||||||
public class ItemWithDetailsAdapter extends ArrayAdapter<ItemWithDetails> {
|
public class ItemWithDetailsAdapter extends AbstractItemAdapter<ItemWithDetails> {
|
||||||
|
|
||||||
public static final int SIZE_SMALL = 1;
|
|
||||||
public static final int SIZE_MEDIUM = 2;
|
|
||||||
public static final int SIZE_LARGE = 3;
|
|
||||||
private final Context context;
|
|
||||||
private boolean horizontalAlignment;
|
|
||||||
private int size = SIZE_MEDIUM;
|
|
||||||
|
|
||||||
public ItemWithDetailsAdapter(Context context, List<ItemWithDetails> items) {
|
public ItemWithDetailsAdapter(Context context, List<ItemWithDetails> items) {
|
||||||
super(context, 0, items);
|
super(context, items);
|
||||||
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHorizontalAlignment(boolean horizontalAlignment) {
|
|
||||||
this.horizontalAlignment = horizontalAlignment;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View view, ViewGroup parent) {
|
protected String getName(ItemWithDetails item) {
|
||||||
ItemWithDetails item = getItem(position);
|
return item.getName();
|
||||||
|
|
||||||
if (view == null) {
|
|
||||||
LayoutInflater inflater = (LayoutInflater) context
|
|
||||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
|
|
||||||
if (horizontalAlignment) {
|
|
||||||
view = inflater.inflate(R.layout.item_with_details_horizontal, parent, false);
|
|
||||||
} else {
|
|
||||||
switch (size) {
|
|
||||||
case SIZE_SMALL:
|
|
||||||
view = inflater.inflate(R.layout.item_with_details_small, parent, false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
view = inflater.inflate(R.layout.item_with_details, parent, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImageView iconView = (ImageView) view.findViewById(R.id.item_image);
|
|
||||||
TextView nameView = (TextView) view.findViewById(R.id.item_name);
|
|
||||||
TextView detailsView = (TextView) view.findViewById(R.id.item_details);
|
|
||||||
|
|
||||||
nameView.setText(item.getName());
|
|
||||||
detailsView.setText(item.getDetails());
|
|
||||||
iconView.setImageResource(item.getIcon());
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSize(int size) {
|
@Override
|
||||||
this.size = size;
|
protected String getDetails(ItemWithDetails item) {
|
||||||
|
return item.getDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
@Override
|
||||||
return size;
|
protected int getIcon(ItemWithDetails item) {
|
||||||
|
return item.getIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
/* Copyright (C) 2015-2017 Carsten Pfeiffer
|
|
||||||
|
|
||||||
This file is part of Gadgetbridge.
|
|
||||||
|
|
||||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published
|
|
||||||
by the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Gadgetbridge is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
package nodomain.freeyourgadget.gadgetbridge.database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains the configuration used for particular activity samples.
|
|
||||||
*/
|
|
||||||
public class UsedConfiguration {
|
|
||||||
String fwVersion;
|
|
||||||
String userName;
|
|
||||||
short userWeight;
|
|
||||||
short userSize;
|
|
||||||
// ...
|
|
||||||
int usedFrom; // timestamp
|
|
||||||
int usedUntil; // timestamp
|
|
||||||
short sleepGoal; // minutes
|
|
||||||
short stepsGoal;
|
|
||||||
}
|
|
@ -124,4 +124,9 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
|||||||
public int getBondingStyle(GBDevice device) {
|
public int getBondingStyle(GBDevice device) {
|
||||||
return BONDING_STYLE_ASK;
|
return BONDING_STYLE_ASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsActivityTracks() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,14 @@ public interface DeviceCoordinator {
|
|||||||
*/
|
*/
|
||||||
boolean supportsActivityTracking();
|
boolean supportsActivityTracking();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the device supports recording dedicated activity tracks, like
|
||||||
|
* walking, hiking, running, swimming, etc. and retrieving the recorded
|
||||||
|
* data. This is different from the constant activity tracking since the tracks are
|
||||||
|
* usually recorded with additional features, like e.g. GPS.
|
||||||
|
*/
|
||||||
|
boolean supportsActivityTracks();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if activity data fetching is supported AND possible at this
|
* Returns true if activity data fetching is supported AND possible at this
|
||||||
* very moment. This will consider the device state (being connected/disconnected/busy...)
|
* very moment. This will consider the device state (being connected/disconnected/busy...)
|
||||||
@ -228,5 +236,4 @@ public interface DeviceCoordinator {
|
|||||||
* This can be live HR, steps etc.
|
* This can be live HR, steps etc.
|
||||||
*/
|
*/
|
||||||
boolean supportsRealtimeData();
|
boolean supportsRealtimeData();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,206 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
|
||||||
|
public class BipActivitySummary extends BaseActivitySummary {
|
||||||
|
private int version;
|
||||||
|
private float distanceMeters;
|
||||||
|
private float ascentMeters;
|
||||||
|
private float descentMeters;
|
||||||
|
private float minAltitude;
|
||||||
|
private float maxAltitude;
|
||||||
|
private int minLatitude;
|
||||||
|
private int maxLatitude;
|
||||||
|
private int minLongitude;
|
||||||
|
private int maxLongitude;
|
||||||
|
private long steps;
|
||||||
|
private long activeTimeSeconds;
|
||||||
|
private float caloriesBurnt;
|
||||||
|
private float maxSpeed;
|
||||||
|
private float minPace;
|
||||||
|
private float maxPace;
|
||||||
|
private float totalStride;
|
||||||
|
private long timeAscent;
|
||||||
|
private long timeDescent;
|
||||||
|
private long timeFlat;
|
||||||
|
private int averageHR;
|
||||||
|
private int averagePace;
|
||||||
|
private int averageStride;
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public long getSteps() {
|
||||||
|
// return steps;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getDistanceMeters() {
|
||||||
|
// return distanceMeters;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getAscentMeters() {
|
||||||
|
// return ascentMeters;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getDescentMeters() {
|
||||||
|
// return descentMeters;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getMinAltitude() {
|
||||||
|
// return minAltitude;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getMaxAltitude() {
|
||||||
|
// return maxAltitude;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getCalories() {
|
||||||
|
// return caloriesBurnt;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getMaxSpeed() {
|
||||||
|
// return maxSpeed;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getMinSpeed() {
|
||||||
|
// return minPace;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public float getAverageSpeed() {
|
||||||
|
// return averagePace;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDistanceMeters(float distanceMeters) {
|
||||||
|
this.distanceMeters = distanceMeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAscentMeters(float ascentMeters) {
|
||||||
|
this.ascentMeters = ascentMeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescentMeters(float descentMeters) {
|
||||||
|
this.descentMeters = descentMeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinAltitude(float minAltitude) {
|
||||||
|
this.minAltitude = minAltitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxAltitude(float maxAltitude) {
|
||||||
|
this.maxAltitude = maxAltitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinLatitude(int minLatitude) {
|
||||||
|
this.minLatitude = minLatitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLatitude(int maxLatitude) {
|
||||||
|
this.maxLatitude = maxLatitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinLongitude(int minLongitude) {
|
||||||
|
this.minLongitude = minLongitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLongitude(int maxLongitude) {
|
||||||
|
this.maxLongitude = maxLongitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSteps(long steps) {
|
||||||
|
this.steps = steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveTimeSeconds(long activeTimeSeconds) {
|
||||||
|
this.activeTimeSeconds = activeTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaloriesBurnt(float caloriesBurnt) {
|
||||||
|
this.caloriesBurnt = caloriesBurnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxSpeed(float maxSpeed) {
|
||||||
|
this.maxSpeed = maxSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinPace(float minPace) {
|
||||||
|
this.minPace = minPace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxPace(float maxPace) {
|
||||||
|
this.maxPace = maxPace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalStride(float totalStride) {
|
||||||
|
this.totalStride = totalStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getTotalStride() {
|
||||||
|
return totalStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeAscent(long timeAscent) {
|
||||||
|
this.timeAscent = timeAscent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeAscent() {
|
||||||
|
return timeAscent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeDescent(long timeDescent) {
|
||||||
|
this.timeDescent = timeDescent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeDescent() {
|
||||||
|
return timeDescent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeFlat(long timeFlat) {
|
||||||
|
this.timeFlat = timeFlat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimeFlat() {
|
||||||
|
return timeFlat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAverageHR(int averageHR) {
|
||||||
|
this.averageHR = averageHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAverageHR() {
|
||||||
|
return averageHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAveragePace(int averagePace) {
|
||||||
|
this.averagePace = averagePace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAveragePace() {
|
||||||
|
return averagePace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAverageStride(int averageStride) {
|
||||||
|
this.averageStride = averageStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAverageStride() {
|
||||||
|
return averageStride;
|
||||||
|
}
|
||||||
|
}
|
@ -63,4 +63,9 @@ public class AmazfitBipCoordinator extends HuamiCoordinator {
|
|||||||
public boolean supportsHeartRateMeasurement(GBDevice device) {
|
public boolean supportsHeartRateMeasurement(GBDevice device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsActivityTracks() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,7 @@ public class AmazfitBipService {
|
|||||||
public static final byte[] COMMAND_SET_LANGUAGE_SIMPLIFIED_CHINESE = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x00};
|
public static final byte[] COMMAND_SET_LANGUAGE_SIMPLIFIED_CHINESE = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x00};
|
||||||
public static final byte[] COMMAND_SET_LANGUAGE_TRADITIONAL_CHINESE = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x01};
|
public static final byte[] COMMAND_SET_LANGUAGE_TRADITIONAL_CHINESE = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x01};
|
||||||
public static final byte[] COMMAND_SET_LANGUAGE_ENGLISH = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x02};
|
public static final byte[] COMMAND_SET_LANGUAGE_ENGLISH = new byte[]{ENDPOINT_DISPLAY, 0x13, 0x00, 0x02};
|
||||||
|
|
||||||
|
public static final byte COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES = 0x05;
|
||||||
|
public static final byte COMMAND_ACTIVITY_DATA_TYPE_SPORTS_DETAILS = 0x06;
|
||||||
}
|
}
|
||||||
|
@ -20,43 +20,14 @@ package nodomain.freeyourgadget.gadgetbridge.devices.miband;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.dao.query.QueryBuilder;
|
import de.greenrobot.dao.query.QueryBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Const;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
import static nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Const.*;
|
||||||
|
|
||||||
public class MiBand2SampleProvider extends AbstractMiBandSampleProvider {
|
public class MiBand2SampleProvider extends AbstractMiBandSampleProvider {
|
||||||
// these come from Mi1
|
|
||||||
// public static final int TYPE_LIGHT_SLEEP = 5;
|
|
||||||
// public static final int TYPE_ACTIVITY = -1;
|
|
||||||
// public static final int TYPE_UNKNOWN = -1;
|
|
||||||
// public static final int TYPE_NONWEAR = 3;
|
|
||||||
// public static final int TYPE_CHARGING = 6;
|
|
||||||
|
|
||||||
|
|
||||||
// observed the following values so far:
|
|
||||||
// 00 01 02 09 0a 0b 0c 10 11
|
|
||||||
|
|
||||||
// 0 = same activity kind as before
|
|
||||||
// 1 = light activity walking?
|
|
||||||
// 3 = definitely non-wear
|
|
||||||
// 9 = probably light sleep, definitely some kind of sleep
|
|
||||||
// 10 = ignore, except for hr (if valid)
|
|
||||||
// 11 = probably deep sleep
|
|
||||||
// 12 = definitely wake up
|
|
||||||
// 17 = definitely not sleep related
|
|
||||||
|
|
||||||
public static final int TYPE_UNSET = -1;
|
|
||||||
public static final int TYPE_NO_CHANGE = 0;
|
|
||||||
public static final int TYPE_ACTIVITY = 1;
|
|
||||||
public static final int TYPE_RUNNING = 2;
|
|
||||||
public static final int TYPE_NONWEAR = 3;
|
|
||||||
public static final int TYPE_CHARGING = 6;
|
|
||||||
public static final int TYPE_LIGHT_SLEEP = 9;
|
|
||||||
public static final int TYPE_IGNORE = 10;
|
|
||||||
public static final int TYPE_DEEP_SLEEP = 11;
|
|
||||||
public static final int TYPE_WAKE_UP = 12;
|
|
||||||
|
|
||||||
public MiBand2SampleProvider(GBDevice device, DaoSession session) {
|
public MiBand2SampleProvider(GBDevice device, DaoSession session) {
|
||||||
super(device, session);
|
super(device, session);
|
||||||
@ -117,39 +88,11 @@ public class MiBand2SampleProvider extends AbstractMiBandSampleProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int normalizeType(int rawType) {
|
public int normalizeType(int rawType) {
|
||||||
switch (rawType) {
|
return MiBand2Const.toActivityKind(rawType);
|
||||||
case TYPE_DEEP_SLEEP:
|
|
||||||
return ActivityKind.TYPE_DEEP_SLEEP;
|
|
||||||
case TYPE_LIGHT_SLEEP:
|
|
||||||
return ActivityKind.TYPE_LIGHT_SLEEP;
|
|
||||||
case TYPE_ACTIVITY:
|
|
||||||
case TYPE_RUNNING:
|
|
||||||
case TYPE_WAKE_UP:
|
|
||||||
return ActivityKind.TYPE_ACTIVITY;
|
|
||||||
case TYPE_NONWEAR:
|
|
||||||
return ActivityKind.TYPE_NOT_WORN;
|
|
||||||
case TYPE_CHARGING:
|
|
||||||
return ActivityKind.TYPE_NOT_WORN; //I believe it's a safe assumption
|
|
||||||
default:
|
|
||||||
case TYPE_UNSET: // fall through
|
|
||||||
return ActivityKind.TYPE_UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int toRawActivityKind(int activityKind) {
|
public int toRawActivityKind(int activityKind) {
|
||||||
switch (activityKind) {
|
return MiBand2Const.toRawActivityType(activityKind);
|
||||||
case ActivityKind.TYPE_ACTIVITY:
|
|
||||||
return TYPE_ACTIVITY;
|
|
||||||
case ActivityKind.TYPE_DEEP_SLEEP:
|
|
||||||
return TYPE_DEEP_SLEEP;
|
|
||||||
case ActivityKind.TYPE_LIGHT_SLEEP:
|
|
||||||
return TYPE_LIGHT_SLEEP;
|
|
||||||
case ActivityKind.TYPE_NOT_WORN:
|
|
||||||
return TYPE_NONWEAR;
|
|
||||||
case ActivityKind.TYPE_UNKNOWN: // fall through
|
|
||||||
default:
|
|
||||||
return TYPE_UNSET;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.devices.miband2;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
|
|
||||||
|
public class MiBand2Const {
|
||||||
|
// observed the following values so far:
|
||||||
|
// 00 01 02 09 0a 0b 0c 10 11
|
||||||
|
|
||||||
|
// 0 = same activity kind as before
|
||||||
|
// 1 = light activity walking?
|
||||||
|
// 3 = definitely non-wear
|
||||||
|
// 9 = probably light sleep, definitely some kind of sleep
|
||||||
|
// 10 = ignore, except for hr (if valid)
|
||||||
|
// 11 = probably deep sleep
|
||||||
|
// 12 = definitely wake up
|
||||||
|
// 17 = definitely not sleep related
|
||||||
|
|
||||||
|
public static final int TYPE_UNSET = -1;
|
||||||
|
public static final int TYPE_NO_CHANGE = 0;
|
||||||
|
public static final int TYPE_ACTIVITY = 1;
|
||||||
|
public static final int TYPE_RUNNING = 2;
|
||||||
|
public static final int TYPE_NONWEAR = 3;
|
||||||
|
public static final int TYPE_RIDE_BIKE = 4;
|
||||||
|
public static final int TYPE_CHARGING = 6;
|
||||||
|
public static final int TYPE_LIGHT_SLEEP = 9;
|
||||||
|
public static final int TYPE_IGNORE = 10;
|
||||||
|
public static final int TYPE_DEEP_SLEEP = 11;
|
||||||
|
public static final int TYPE_WAKE_UP = 12;
|
||||||
|
|
||||||
|
public static int toActivityKind(int rawType) {
|
||||||
|
switch (rawType) {
|
||||||
|
case TYPE_DEEP_SLEEP:
|
||||||
|
return ActivityKind.TYPE_DEEP_SLEEP;
|
||||||
|
case TYPE_LIGHT_SLEEP:
|
||||||
|
return ActivityKind.TYPE_LIGHT_SLEEP;
|
||||||
|
case TYPE_ACTIVITY:
|
||||||
|
case TYPE_RUNNING:
|
||||||
|
case TYPE_WAKE_UP:
|
||||||
|
return ActivityKind.TYPE_ACTIVITY;
|
||||||
|
case TYPE_NONWEAR:
|
||||||
|
return ActivityKind.TYPE_NOT_WORN;
|
||||||
|
case TYPE_CHARGING:
|
||||||
|
return ActivityKind.TYPE_NOT_WORN; //I believe it's a safe assumption
|
||||||
|
case TYPE_RIDE_BIKE:
|
||||||
|
return ActivityKind.TYPE_BIKING;
|
||||||
|
default:
|
||||||
|
case TYPE_UNSET: // fall through
|
||||||
|
return ActivityKind.TYPE_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toRawActivityType(int activityKind) {
|
||||||
|
switch (activityKind) {
|
||||||
|
case ActivityKind.TYPE_ACTIVITY:
|
||||||
|
return TYPE_ACTIVITY;
|
||||||
|
case ActivityKind.TYPE_DEEP_SLEEP:
|
||||||
|
return TYPE_DEEP_SLEEP;
|
||||||
|
case ActivityKind.TYPE_LIGHT_SLEEP:
|
||||||
|
return TYPE_LIGHT_SLEEP;
|
||||||
|
case ActivityKind.TYPE_NOT_WORN:
|
||||||
|
return TYPE_NONWEAR;
|
||||||
|
case ActivityKind.TYPE_UNKNOWN: // fall through
|
||||||
|
default:
|
||||||
|
return TYPE_UNSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.export;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
|
|
||||||
|
public interface ActivityTrackExporter {
|
||||||
|
@NonNull
|
||||||
|
String getDefaultFileName(@NonNull ActivityTrack track);
|
||||||
|
|
||||||
|
void performExport(ActivityTrack track, File targetFile) throws IOException;
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.export;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.GPSCoordinate;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
|
||||||
|
public class GPXExporter implements ActivityTrackExporter {
|
||||||
|
private static final String NS_DEFAULT = "";
|
||||||
|
private static final String NS_DEFAULT_URI = "http://www.topografix.com/GPX/1/1";
|
||||||
|
private static final String NS_DEFAULT_PREFIX = "";
|
||||||
|
private static final String NS_TRACKPOINT_EXTENSION = "gpxtpx";
|
||||||
|
private static final String NS_TRACKPOINT_EXTENSION_URI = "http://www.garmin.com/xmlschemas/TrackPointExtension/v1";
|
||||||
|
private static final String NS_XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
|
||||||
|
|
||||||
|
private String creator;
|
||||||
|
private boolean includeHeartRate = true;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getDefaultFileName(@NonNull ActivityTrack track) {
|
||||||
|
return FileUtils.makeValidFileName(track.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performExport(ActivityTrack track, File targetFile) throws IOException {
|
||||||
|
String encoding = StandardCharsets.UTF_8.name();
|
||||||
|
XmlSerializer ser = Xml.newSerializer();
|
||||||
|
try {
|
||||||
|
ser.setOutput(new FileOutputStream(targetFile), encoding);
|
||||||
|
ser.startDocument(encoding, Boolean.TRUE);
|
||||||
|
ser.setPrefix("xsi", NS_XSI_URI);
|
||||||
|
ser.setPrefix(NS_DEFAULT_PREFIX, NS_DEFAULT);
|
||||||
|
|
||||||
|
ser.startTag(NS_DEFAULT, "gpx");
|
||||||
|
ser.attribute(NS_DEFAULT, "version", "1.1");
|
||||||
|
ser.attribute(NS_DEFAULT, "creator", getCreator());
|
||||||
|
ser.attribute(NS_XSI_URI, "schemaLocation", NS_DEFAULT_URI + " " + "http://www.topografix.com/GPX/1/1/gpx.xsd");
|
||||||
|
|
||||||
|
exportMetadata(ser, track);
|
||||||
|
exportTrack(ser, track);
|
||||||
|
|
||||||
|
ser.endTag(NS_DEFAULT, "gpx");
|
||||||
|
ser.endDocument();
|
||||||
|
} finally {
|
||||||
|
ser.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportMetadata(XmlSerializer ser, ActivityTrack track) throws IOException {
|
||||||
|
ser.startTag(NS_DEFAULT, "metadata");
|
||||||
|
ser.startTag(NS_DEFAULT, "name").text(track.getName()).endTag(NS_DEFAULT, "name");
|
||||||
|
|
||||||
|
ser.startTag(NS_DEFAULT, "author");
|
||||||
|
ser.startTag(NS_DEFAULT, "name").text(track.getUser().getName()).endTag(NS_DEFAULT, "name");
|
||||||
|
ser.endTag(NS_DEFAULT, "author");
|
||||||
|
|
||||||
|
ser.startTag(NS_DEFAULT, "time").text(formatTime(new Date())).endTag(NS_DEFAULT, "time");
|
||||||
|
|
||||||
|
ser.endTag(NS_DEFAULT, "metadata");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTime(Date date) {
|
||||||
|
return DateTimeUtils.formatIso8601(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportTrack(XmlSerializer ser, ActivityTrack track) throws IOException {
|
||||||
|
ser.startTag(NS_DEFAULT, "trk");
|
||||||
|
ser.startTag(NS_DEFAULT, "trkseg");
|
||||||
|
|
||||||
|
List<ActivityPoint> trackPoints = track.getTrackPoints();
|
||||||
|
String source = getSource(track);
|
||||||
|
for (ActivityPoint point : trackPoints) {
|
||||||
|
exportTrackPoint(ser, point, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
ser.endTag(NS_DEFAULT, "trkseg");
|
||||||
|
ser.endTag(NS_DEFAULT, "trk");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSource(ActivityTrack track) {
|
||||||
|
return track.getDevice().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportTrackPoint(XmlSerializer ser, ActivityPoint point, String source) throws IOException {
|
||||||
|
GPSCoordinate location = point.getLocation();
|
||||||
|
if (location == null) {
|
||||||
|
return; // skip invalid points, that just contain hr data, for example
|
||||||
|
}
|
||||||
|
ser.startTag(NS_DEFAULT, "trkpt");
|
||||||
|
ser.attribute(NS_DEFAULT, "lon", formatLocation(location.getLongitude()));
|
||||||
|
ser.attribute(NS_DEFAULT, "lat", formatLocation(location.getLatitude()));
|
||||||
|
ser.startTag(NS_DEFAULT, "ele").text(formatLocation(location.getAltitude())).endTag(NS_DEFAULT, "ele");
|
||||||
|
ser.startTag(NS_DEFAULT, "time").text(formatTime(point.getTime())).endTag(NS_DEFAULT, "time");
|
||||||
|
String description = point.getDescription();
|
||||||
|
if (description != null) {
|
||||||
|
ser.startTag(NS_DEFAULT, "desc").text(description).endTag(NS_DEFAULT, "desc");
|
||||||
|
}
|
||||||
|
ser.startTag(NS_DEFAULT, "src").text(source).endTag(NS_DEFAULT, "src");
|
||||||
|
|
||||||
|
exportTrackpointExtensions(ser, point);
|
||||||
|
|
||||||
|
ser.endTag(NS_DEFAULT, "trkpt");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exportTrackpointExtensions(XmlSerializer ser, ActivityPoint point) throws IOException {
|
||||||
|
if (!includeHeartRate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hr = point.getHeartRate();
|
||||||
|
if (!HeartRateUtils.isValidHeartRateValue(hr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ser.startTag(NS_DEFAULT, "extensions");
|
||||||
|
|
||||||
|
ser.setPrefix(NS_TRACKPOINT_EXTENSION, NS_TRACKPOINT_EXTENSION_URI);
|
||||||
|
ser.startTag(NS_TRACKPOINT_EXTENSION_URI, "hr").text(String.valueOf(hr)).endTag(NS_TRACKPOINT_EXTENSION_URI, "hr");
|
||||||
|
|
||||||
|
ser.endTag(NS_DEFAULT, "extensions");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatLocation(double value) {
|
||||||
|
return new BigDecimal(value).setScale(GPSCoordinate.GPS_DECIMAL_DEGREES_SCALE, RoundingMode.HALF_UP).toPlainString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreator() {
|
||||||
|
return creator; // TODO: move to some kind of BrandingInfo class
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncludeHeartRate(boolean includeHeartRate) {
|
||||||
|
this.includeHeartRate = includeHeartRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isIncludeHeartRate() {
|
||||||
|
return includeHeartRate;
|
||||||
|
}
|
||||||
|
}
|
@ -17,8 +17,12 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.model;
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||||
|
|
||||||
public class ActivityKind {
|
public class ActivityKind {
|
||||||
@ -28,9 +32,13 @@ public class ActivityKind {
|
|||||||
public static final int TYPE_LIGHT_SLEEP = 2;
|
public static final int TYPE_LIGHT_SLEEP = 2;
|
||||||
public static final int TYPE_DEEP_SLEEP = 4;
|
public static final int TYPE_DEEP_SLEEP = 4;
|
||||||
public static final int TYPE_NOT_WORN = 8;
|
public static final int TYPE_NOT_WORN = 8;
|
||||||
|
public static final int TYPE_RUNNING = 16;
|
||||||
|
public static final int TYPE_WALKING = 32;
|
||||||
|
public static final int TYPE_SWIMMING = 64;
|
||||||
|
|
||||||
public static final int TYPE_SLEEP = TYPE_LIGHT_SLEEP | TYPE_DEEP_SLEEP;
|
public static final int TYPE_SLEEP = TYPE_LIGHT_SLEEP | TYPE_DEEP_SLEEP;
|
||||||
public static final int TYPE_ALL = TYPE_ACTIVITY | TYPE_SLEEP | TYPE_NOT_WORN;
|
public static final int TYPE_ALL = TYPE_ACTIVITY | TYPE_SLEEP | TYPE_NOT_WORN;
|
||||||
|
public static final int TYPE_BIKING = 128;
|
||||||
|
|
||||||
public static int[] mapToDBActivityTypes(int types, SampleProvider provider) {
|
public static int[] mapToDBActivityTypes(int types, SampleProvider provider) {
|
||||||
int[] result = new int[3];
|
int[] result = new int[3];
|
||||||
@ -47,7 +55,68 @@ public class ActivityKind {
|
|||||||
if ((types & ActivityKind.TYPE_NOT_WORN) != 0) {
|
if ((types & ActivityKind.TYPE_NOT_WORN) != 0) {
|
||||||
result[i++] = provider.toRawActivityKind(TYPE_NOT_WORN);
|
result[i++] = provider.toRawActivityKind(TYPE_NOT_WORN);
|
||||||
}
|
}
|
||||||
|
if ((types & ActivityKind.TYPE_RUNNING) != 0) {
|
||||||
|
result[i++] = provider.toRawActivityKind(TYPE_RUNNING);
|
||||||
|
}
|
||||||
|
if ((types & ActivityKind.TYPE_WALKING) != 0) {
|
||||||
|
result[i++] = provider.toRawActivityKind(TYPE_WALKING);
|
||||||
|
}
|
||||||
|
if ((types & ActivityKind.TYPE_SWIMMING) != 0) {
|
||||||
|
result[i++] = provider.toRawActivityKind(TYPE_SWIMMING);
|
||||||
|
}
|
||||||
|
if ((types & ActivityKind.TYPE_BIKING) != 0) {
|
||||||
|
result[i++] = provider.toRawActivityKind(TYPE_BIKING);
|
||||||
|
}
|
||||||
return Arrays.copyOf(result, i);
|
return Arrays.copyOf(result, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String asString(int kind, Context context) {
|
||||||
|
switch (kind) {
|
||||||
|
case TYPE_NOT_MEASURED:
|
||||||
|
return context.getString(R.string.activity_type_not_measured);
|
||||||
|
case TYPE_ACTIVITY:
|
||||||
|
return context.getString(R.string.activity_type_activity);
|
||||||
|
case TYPE_LIGHT_SLEEP:
|
||||||
|
return context.getString(R.string.activity_type_light_sleep);
|
||||||
|
case TYPE_DEEP_SLEEP:
|
||||||
|
return context.getString(R.string.activity_type_deep_sleep);
|
||||||
|
case TYPE_NOT_WORN:
|
||||||
|
return context.getString(R.string.activity_type_not_worn);
|
||||||
|
case TYPE_RUNNING:
|
||||||
|
return context.getString(R.string.activity_type_running);
|
||||||
|
case TYPE_WALKING:
|
||||||
|
return context.getString(R.string.activity_type_walking);
|
||||||
|
case TYPE_SWIMMING:
|
||||||
|
return context.getString(R.string.activity_type_swimming);
|
||||||
|
case TYPE_BIKING:
|
||||||
|
return context.getString(R.string.activity_type_biking);
|
||||||
|
case TYPE_UNKNOWN:
|
||||||
|
default:
|
||||||
|
return context.getString(R.string.activity_type_unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
public static int getIconId(int kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case TYPE_NOT_MEASURED:
|
||||||
|
return R.drawable.ic_activity_not_measured;
|
||||||
|
case TYPE_LIGHT_SLEEP:
|
||||||
|
return R.drawable.ic_activity_light_sleep;
|
||||||
|
case TYPE_DEEP_SLEEP:
|
||||||
|
return R.drawable.ic_activity_deep_sleep;
|
||||||
|
case TYPE_RUNNING:
|
||||||
|
return R.drawable.ic_activity_running;
|
||||||
|
case TYPE_WALKING:
|
||||||
|
return R.drawable.ic_activity_walking;
|
||||||
|
case TYPE_BIKING:
|
||||||
|
return R.drawable.ic_activity_biking;
|
||||||
|
case TYPE_SWIMMING: // fall through
|
||||||
|
case TYPE_NOT_WORN: // fall through
|
||||||
|
case TYPE_ACTIVITY: // fall through
|
||||||
|
case TYPE_UNKNOWN: // fall through
|
||||||
|
default:
|
||||||
|
return R.drawable.ic_activity_unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
// https://www8.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||||
|
/*
|
||||||
|
<trkpt lat="54.8591470" lon="-1.5754310">
|
||||||
|
<ele>29.2</ele>
|
||||||
|
<time>2015-07-26T07:43:42Z</time>
|
||||||
|
<extensions>
|
||||||
|
<gpxtpx:TrackPointExtension>
|
||||||
|
<gpxtpx:atemp>11</gpxtpx:atemp>
|
||||||
|
<gpxtpx:hr>92</gpxtpx:hr>
|
||||||
|
<gpxtpx:cad>0</gpxtpx:cad>
|
||||||
|
</gpxtpx:TrackPointExtension>
|
||||||
|
</extensions>
|
||||||
|
</trkpt>
|
||||||
|
*/
|
||||||
|
public class ActivityPoint {
|
||||||
|
private Date time;
|
||||||
|
private GPSCoordinate location;
|
||||||
|
private int heartRate;
|
||||||
|
private long speed4;
|
||||||
|
private long speed5;
|
||||||
|
private long speed6;
|
||||||
|
|
||||||
|
// e.g. to describe a pause during the activity
|
||||||
|
private @Nullable String description;
|
||||||
|
|
||||||
|
public ActivityPoint() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActivityPoint(Date time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime(Date time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(@Nullable String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GPSCoordinate getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(GPSCoordinate location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeartRate() {
|
||||||
|
return heartRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeartRate(int heartRate) {
|
||||||
|
this.heartRate = heartRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSpeed4() {
|
||||||
|
return speed4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpeed4(long speed4) {
|
||||||
|
this.speed4 = speed4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSpeed5() {
|
||||||
|
return speed5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpeed5(long speed5) {
|
||||||
|
this.speed5 = speed5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSpeed6() {
|
||||||
|
return speed6;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpeed6(long speed6) {
|
||||||
|
this.speed6 = speed6;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Summarized information about a temporal activity.
|
||||||
|
*
|
||||||
|
* // TODO: split into separate entities?
|
||||||
|
*/
|
||||||
|
public interface ActivitySummary extends Serializable {
|
||||||
|
String getName();
|
||||||
|
Date getStartTime();
|
||||||
|
Date getEndTime();
|
||||||
|
|
||||||
|
int getActivityKind();
|
||||||
|
String getGpxTrack();
|
||||||
|
|
||||||
|
long getDeviceId();
|
||||||
|
|
||||||
|
long getUserId();
|
||||||
|
// long getSteps();
|
||||||
|
// float getDistanceMeters();
|
||||||
|
// float getAscentMeters();
|
||||||
|
// float getDescentMeters();
|
||||||
|
// float getMinAltitude();
|
||||||
|
// float getMaxAltitude();
|
||||||
|
// float getCalories();
|
||||||
|
//
|
||||||
|
// float getMaxSpeed();
|
||||||
|
// float getMinSpeed();
|
||||||
|
// float getAverageSpeed();
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
|
||||||
|
public class ActivityTrack {
|
||||||
|
private Date baseTime;
|
||||||
|
private Device device;
|
||||||
|
private User user;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
|
||||||
|
public void setBaseTime(Date baseTime) {
|
||||||
|
this.baseTime = baseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice(Device device) {
|
||||||
|
this.device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrackPoints(List<ActivityPoint> trackPoints) {
|
||||||
|
this.trackPoints = trackPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ActivityPoint> trackPoints = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addTrackPoint(ActivityPoint point) {
|
||||||
|
trackPoints.add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ActivityPoint> getTrackPoints() {
|
||||||
|
return trackPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getBaseTime() {
|
||||||
|
return baseTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
public final class GPSCoordinate {
|
||||||
|
private final double latitude;
|
||||||
|
private final double longitude;
|
||||||
|
private final double altitude;
|
||||||
|
|
||||||
|
public static final int GPS_DECIMAL_DEGREES_SCALE = 6; // precise to 111.132mm at equator: https://en.wikipedia.org/wiki/Decimal_degrees
|
||||||
|
|
||||||
|
public GPSCoordinate(double longitude, double latitude, double altitude) {
|
||||||
|
this.longitude = longitude;
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.altitude = altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAltitude() {
|
||||||
|
return altitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
GPSCoordinate that = (GPSCoordinate) o;
|
||||||
|
|
||||||
|
if (Double.compare(that.getLatitude(), getLatitude()) != 0) return false;
|
||||||
|
if (Double.compare(that.getLongitude(), getLongitude()) != 0) return false;
|
||||||
|
return Double.compare(that.getAltitude(), getAltitude()) == 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
long temp;
|
||||||
|
temp = Double.doubleToLongBits(getLatitude());
|
||||||
|
result = (int) (temp ^ (temp >>> 32));
|
||||||
|
temp = Double.doubleToLongBits(getLongitude());
|
||||||
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
temp = Double.doubleToLongBits(getAltitude());
|
||||||
|
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatLocation(double value) {
|
||||||
|
return new BigDecimal(value).setScale(8, RoundingMode.HALF_UP).toPlainString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "lon: " + formatLocation(longitude) + ", lat: " + formatLocation(latitude) + ", alt: " + formatLocation(altitude) + "m";
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotificat
|
|||||||
* Provides methods to convert standard BLE units to byte sequences and vice versa.
|
* Provides methods to convert standard BLE units to byte sequences and vice versa.
|
||||||
*/
|
*/
|
||||||
public class BLETypeConversions {
|
public class BLETypeConversions {
|
||||||
|
public static final int TZ_FLAG_NONE = 0;
|
||||||
|
public static final int TZ_FLAG_INCLUDE_DST_IN_TZ = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a timestamp to the byte sequence to be sent to the current time characteristic
|
* Converts a timestamp to the byte sequence to be sent to the current time characteristic
|
||||||
*
|
*
|
||||||
@ -157,10 +160,33 @@ public class BLETypeConversions {
|
|||||||
return createCalendar();
|
return createCalendar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long toUnsigned(int unsignedInt) {
|
||||||
|
return ((long) unsignedInt) & 0xffffffffL;
|
||||||
|
}
|
||||||
|
public static int toUnsigned(short value) {
|
||||||
|
return value & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toUnsigned(byte value) {
|
||||||
|
return value & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toUint16(byte value) {
|
||||||
|
return toUnsigned(value);
|
||||||
|
}
|
||||||
|
|
||||||
public static int toUint16(byte... bytes) {
|
public static int toUint16(byte... bytes) {
|
||||||
return (bytes[0] & 0xff) | ((bytes[1] & 0xff) << 8);
|
return (bytes[0] & 0xff) | ((bytes[1] & 0xff) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int toInt16(byte... bytes) {
|
||||||
|
return (short) (bytes[0] & 0xff | ((bytes[1] & 0xff) << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int toUint32(byte... bytes) {
|
||||||
|
return (bytes[0] & 0xff) | ((bytes[1] & 0xff) << 8) | ((bytes[2] & 0xff) << 16) | ((bytes[3] & 0xff) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] fromUint16(int value) {
|
public static byte[] fromUint16(int value) {
|
||||||
return new byte[] {
|
return new byte[] {
|
||||||
(byte) (value & 0xff),
|
(byte) (value & 0xff),
|
||||||
@ -223,7 +249,20 @@ public class BLETypeConversions {
|
|||||||
* @return sint8 value from -48..+56
|
* @return sint8 value from -48..+56
|
||||||
*/
|
*/
|
||||||
public static byte mapTimeZone(TimeZone timeZone) {
|
public static byte mapTimeZone(TimeZone timeZone) {
|
||||||
int utcOffsetInHours = (timeZone.getRawOffset() / (1000 * 60 * 60));
|
return mapTimeZone(timeZone, TZ_FLAG_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.time_zone.xml
|
||||||
|
* @param timeZone
|
||||||
|
* @return sint8 value from -48..+56
|
||||||
|
*/
|
||||||
|
public static byte mapTimeZone(TimeZone timeZone, int timezoneFlags) {
|
||||||
|
int offsetMillis = timeZone.getRawOffset();
|
||||||
|
if (timezoneFlags == TZ_FLAG_INCLUDE_DST_IN_TZ) {
|
||||||
|
offsetMillis += timeZone.getDSTSavings();
|
||||||
|
}
|
||||||
|
int utcOffsetInHours = (offsetMillis / (1000 * 60 * 60));
|
||||||
return (byte) (utcOffsetInHours * 4);
|
return (byte) (utcOffsetInHours * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ import java.util.concurrent.BlockingQueue;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
|
||||||
@ -467,10 +468,7 @@ public final class BtLEQueue {
|
|||||||
public void onCharacteristicChanged(BluetoothGatt gatt,
|
public void onCharacteristicChanged(BluetoothGatt gatt,
|
||||||
BluetoothGattCharacteristic characteristic) {
|
BluetoothGattCharacteristic characteristic) {
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
String content = "";
|
String content = Logging.formatBytes(characteristic.getValue());
|
||||||
for (byte b : characteristic.getValue()) {
|
|
||||||
content += String.format(" 0x%1x", b);
|
|
||||||
}
|
|
||||||
LOG.debug("characteristic changed: " + characteristic.getUuid() + " value: " + content);
|
LOG.debug("characteristic changed: " + characteristic.getUuid() + " value: " + content);
|
||||||
}
|
}
|
||||||
if (!checkCorrectGattInstance(gatt, "characteristic changed")) {
|
if (!checkCorrectGattInstance(gatt, "characteristic changed")) {
|
||||||
|
@ -0,0 +1,216 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.GPSCoordinate;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
|
|
||||||
|
public class ActivityDetailsParser {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ActivityDetailsParser.class);
|
||||||
|
|
||||||
|
private static final byte TYPE_GPS = 0;
|
||||||
|
private static final byte TYPE_HR = 1;
|
||||||
|
private static final byte TYPE_UNKNOWN2 = 2;
|
||||||
|
private static final byte TYPE_PAUSE = 3;
|
||||||
|
private static final byte TYPE_SPEED4 = 4;
|
||||||
|
private static final byte TYPE_SPEED5 = 5;
|
||||||
|
private static final byte TYPE_GPS_SPEED6 = 6;
|
||||||
|
|
||||||
|
public static final BigDecimal HUAMI_TO_DECIMAL_DEGREES_DIVISOR = new BigDecimal(3000000.0);
|
||||||
|
private final BaseActivitySummary summary;
|
||||||
|
private final ActivityTrack activityTrack;
|
||||||
|
// private final int version;
|
||||||
|
private final Date baseDate;
|
||||||
|
private long baseLongitude;
|
||||||
|
private long baseLatitude;
|
||||||
|
private int baseAltitude;
|
||||||
|
private ActivityPoint lastActivityPoint;
|
||||||
|
|
||||||
|
public boolean getSkipCounterByte() {
|
||||||
|
return skipCounterByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkipCounterByte(boolean skipCounterByte) {
|
||||||
|
this.skipCounterByte = skipCounterByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean skipCounterByte;
|
||||||
|
|
||||||
|
public ActivityDetailsParser(BaseActivitySummary summary) {
|
||||||
|
this.summary = summary;
|
||||||
|
// this.version = version;
|
||||||
|
// this.baseDate = baseDate;
|
||||||
|
//
|
||||||
|
this.baseLongitude = summary.getBaseLongitude();
|
||||||
|
this.baseLatitude = summary.getBaseLatitude();
|
||||||
|
this.baseAltitude = summary.getBaseAltitude();
|
||||||
|
this.baseDate = summary.getStartTime();
|
||||||
|
|
||||||
|
this.activityTrack = new ActivityTrack();
|
||||||
|
activityTrack.setUser(summary.getUser());
|
||||||
|
activityTrack.setDevice(summary.getDevice());
|
||||||
|
activityTrack.setName(summary.getName() + "-" + summary.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActivityTrack parse(byte[] bytes) throws GBException {
|
||||||
|
int i = 0;
|
||||||
|
try {
|
||||||
|
long totalTimeOffset = 0;
|
||||||
|
int lastTimeOffset = 0;
|
||||||
|
while (i < bytes.length) {
|
||||||
|
if (skipCounterByte && (i % 17) == 0) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte type = bytes[i++];
|
||||||
|
int timeOffset = BLETypeConversions.toUnsigned(bytes[i++]);
|
||||||
|
// handle timeOffset overflows (1 byte, always increasing, relative to base)
|
||||||
|
if (lastTimeOffset <= timeOffset) {
|
||||||
|
timeOffset = timeOffset - lastTimeOffset;
|
||||||
|
lastTimeOffset += timeOffset;
|
||||||
|
} else {
|
||||||
|
lastTimeOffset = timeOffset;
|
||||||
|
}
|
||||||
|
totalTimeOffset += timeOffset;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_GPS:
|
||||||
|
i += consumeGPSAndUpdateBaseLocation(bytes, i, totalTimeOffset);
|
||||||
|
break;
|
||||||
|
case TYPE_HR:
|
||||||
|
i += consumeHeartRate(bytes, i, totalTimeOffset);
|
||||||
|
break;
|
||||||
|
case TYPE_UNKNOWN2:
|
||||||
|
i += consumeUnknown2(bytes, i);
|
||||||
|
break;
|
||||||
|
case TYPE_PAUSE:
|
||||||
|
i += consumePause(bytes, i);
|
||||||
|
break;
|
||||||
|
case TYPE_SPEED4:
|
||||||
|
i += consumeSpeed4(bytes, i);
|
||||||
|
break;
|
||||||
|
case TYPE_SPEED5:
|
||||||
|
i += consumeSpeed5(bytes, i);
|
||||||
|
break;
|
||||||
|
case TYPE_GPS_SPEED6:
|
||||||
|
i += consumeSpeed6(bytes, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IndexOutOfBoundsException ex) {
|
||||||
|
throw new GBException("Error parsing activity details: " + ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return activityTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeGPSAndUpdateBaseLocation(byte[] bytes, int offset, long timeOffset) {
|
||||||
|
int i = 0;
|
||||||
|
int longitudeDelta = BLETypeConversions.toInt16(bytes[offset + i++], bytes[offset + i++]);
|
||||||
|
int latitudeDelta = BLETypeConversions.toInt16(bytes[offset + i++], bytes[offset + i++]);
|
||||||
|
int altitudeDelta = BLETypeConversions.toInt16(bytes[offset + i++], bytes[offset + i++]);
|
||||||
|
|
||||||
|
baseLongitude += longitudeDelta;
|
||||||
|
baseLatitude += latitudeDelta;
|
||||||
|
baseAltitude += altitudeDelta;
|
||||||
|
|
||||||
|
GPSCoordinate coordinate = new GPSCoordinate(
|
||||||
|
convertHuamiValueToDecimalDegrees(baseLongitude),
|
||||||
|
convertHuamiValueToDecimalDegrees(baseLatitude),
|
||||||
|
baseAltitude);
|
||||||
|
|
||||||
|
ActivityPoint ap = getActivityPointFor(timeOffset);
|
||||||
|
ap.setLocation(coordinate);
|
||||||
|
add(ap);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double convertHuamiValueToDecimalDegrees(long huamiValue) {
|
||||||
|
BigDecimal result = new BigDecimal(huamiValue).divide(HUAMI_TO_DECIMAL_DEGREES_DIVISOR, GPSCoordinate.GPS_DECIMAL_DEGREES_SCALE, RoundingMode.HALF_UP);
|
||||||
|
return result.doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeHeartRate(byte[] bytes, int offset, long timeOffsetSeconds) {
|
||||||
|
int v1 = BLETypeConversions.toUint16(bytes[offset]);
|
||||||
|
int v2 = BLETypeConversions.toUint16(bytes[offset + 1]);
|
||||||
|
int v3 = BLETypeConversions.toUint16(bytes[offset + 2]);
|
||||||
|
int v4 = BLETypeConversions.toUint16(bytes[offset + 3]);
|
||||||
|
int v5 = BLETypeConversions.toUint16(bytes[offset + 4]);
|
||||||
|
int v6 = BLETypeConversions.toUint16(bytes[offset + 5]);
|
||||||
|
|
||||||
|
if (v2 == 0 && v3 == 0 && v4 == 0 && v5 == 0 && v6 == 0) {
|
||||||
|
// new version
|
||||||
|
// LOG.info("detected heart rate in 'new' version, where version is: " + summary.getVersion());
|
||||||
|
LOG.info("detected heart rate in 'new' version format");
|
||||||
|
ActivityPoint ap = getActivityPointFor(timeOffsetSeconds);
|
||||||
|
ap.setHeartRate(v1);
|
||||||
|
add(ap);
|
||||||
|
} else {
|
||||||
|
ActivityPoint ap = getActivityPointFor(v1);
|
||||||
|
ap.setHeartRate(v2);
|
||||||
|
add(ap);
|
||||||
|
|
||||||
|
ap = getActivityPointFor(v3);
|
||||||
|
ap.setHeartRate(v4);
|
||||||
|
add(ap);
|
||||||
|
|
||||||
|
ap = getActivityPointFor(v5);
|
||||||
|
ap.setHeartRate(v6);
|
||||||
|
add(ap);
|
||||||
|
}
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActivityPoint getActivityPointFor(long timeOffsetSeconds) {
|
||||||
|
Date time = makeAbsolute(timeOffsetSeconds);
|
||||||
|
// if (lastActivityPoint != null) {
|
||||||
|
// if (lastActivityPoint.getTime().equals(time)) {
|
||||||
|
// return lastActivityPoint;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return new ActivityPoint(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Date makeAbsolute(long timeOffsetSeconds) {
|
||||||
|
return new Date(baseDate.getTime() + timeOffsetSeconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add(ActivityPoint ap) {
|
||||||
|
if (ap != lastActivityPoint) {
|
||||||
|
lastActivityPoint = ap;
|
||||||
|
activityTrack.addTrackPoint(ap);
|
||||||
|
} else {
|
||||||
|
LOG.info("skipping point!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeUnknown2(byte[] bytes, int offset) {
|
||||||
|
return 6; // just guessing...
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumePause(byte[] bytes, int i) {
|
||||||
|
return 6; // just guessing...
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeSpeed4(byte[] bytes, int offset) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeSpeed5(byte[] bytes, int offset) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int consumeSpeed6(byte[] bytes, int offset) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
}
|
@ -44,10 +44,10 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipFetchLogsOperation;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiIcon;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiIcon;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.FetchSportsSummaryOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||||
|
|
||||||
@ -183,7 +183,8 @@ public class AmazfitBipSupport extends MiBand2Support {
|
|||||||
@Override
|
@Override
|
||||||
public void onTestNewFunction() {
|
public void onTestNewFunction() {
|
||||||
try {
|
try {
|
||||||
new AmazfitBipFetchLogsOperation(this).perform();
|
// new AmazfitBipFetchLogsOperation(this).perform();
|
||||||
|
new FetchSportsSummaryOperation(this).perform();
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
LOG.error("Unable to fetch logs", ex);
|
LOG.error("Unable to fetch logs", ex);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleActivityFetchFinish() {
|
protected void handleActivityFetchFinish(boolean success) {
|
||||||
LOG.info("Fetching log data has finished");
|
LOG.info("Fetching log data has finished");
|
||||||
try {
|
try {
|
||||||
logOutputStream.close();
|
logOutputStream.close();
|
||||||
@ -98,7 +98,7 @@ public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation {
|
|||||||
LOG.warn("could not close output stream", e);
|
LOG.warn("could not close output stream", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
super.handleActivityFetchFinish();
|
super.handleActivityFetchFinish(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -114,17 +114,17 @@ public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation {
|
|||||||
bufferActivityData(value);
|
bufferActivityData(value);
|
||||||
} else {
|
} else {
|
||||||
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
|
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void bufferActivityData(@NonNull byte[] value) {
|
protected void bufferActivityData(@NonNull byte[] value) {
|
||||||
try {
|
try {
|
||||||
logOutputStream.write(Arrays.copyOfRange(value, 1, value.length));
|
logOutputStream.write(value, 1, value.length);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("could not write to output stream", e);
|
LOG.warn("could not write to output stream", e);
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ import java.util.Date;
|
|||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -66,6 +67,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.VibrationProfile;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Const;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample;
|
||||||
@ -102,6 +104,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationS
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.RealtimeSamplesSupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.RealtimeSamplesSupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.actions.StopNotificationAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.actions.StopNotificationAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.FetchActivityOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.FetchActivityOperation;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.FetchSportsSummaryOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.InitOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.InitOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.UpdateFirmwareOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.UpdateFirmwareOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
@ -209,6 +212,14 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given date/time (calendar) as a byte sequence, suitable for sending to the
|
||||||
|
* Mi Band 2 (or derivative). The band appears to not handle DST offsets, so we simply add this
|
||||||
|
* to the timezone.
|
||||||
|
* @param calendar
|
||||||
|
* @param precision
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public byte[] getTimeBytes(Calendar calendar, TimeUnit precision) {
|
public byte[] getTimeBytes(Calendar calendar, TimeUnit precision) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
if (precision == TimeUnit.MINUTES) {
|
if (precision == TimeUnit.MINUTES) {
|
||||||
@ -218,7 +229,8 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
|||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Unsupported precision, only MINUTES and SECONDS are supported till now");
|
throw new IllegalArgumentException("Unsupported precision, only MINUTES and SECONDS are supported till now");
|
||||||
}
|
}
|
||||||
byte[] tail = new byte[] { 0, BLETypeConversions.mapTimeZone(calendar.getTimeZone()) }; // 0 = adjust reason bitflags? or DST offset?? , timezone
|
byte[] tail = new byte[] { 0, BLETypeConversions.mapTimeZone(calendar.getTimeZone(), BLETypeConversions.TZ_FLAG_INCLUDE_DST_IN_TZ) };
|
||||||
|
// 0 = adjust reason bitflags? or DST offset?? , timezone
|
||||||
// byte[] tail = new byte[] { 0x2 }; // reason
|
// byte[] tail = new byte[] { 0x2 }; // reason
|
||||||
byte[] all = BLETypeConversions.join(bytes, tail);
|
byte[] all = BLETypeConversions.join(bytes, tail);
|
||||||
return all;
|
return all;
|
||||||
@ -1137,7 +1149,7 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
|||||||
sample.setHeartRate(getHeartrateBpm());
|
sample.setHeartRate(getHeartrateBpm());
|
||||||
sample.setSteps(getSteps());
|
sample.setSteps(getSteps());
|
||||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||||
sample.setRawKind(MiBand2SampleProvider.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that?
|
sample.setRawKind(MiBand2Const.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that?
|
||||||
|
|
||||||
provider.addGBActivitySample(sample);
|
provider.addGBActivitySample(sample);
|
||||||
|
|
||||||
@ -1318,10 +1330,9 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
|||||||
@Override
|
@Override
|
||||||
public void onTestNewFunction() {
|
public void onTestNewFunction() {
|
||||||
try {
|
try {
|
||||||
TransactionBuilder builder = performInitialized("test realtime steps");
|
new FetchSportsSummaryOperation(this).perform();
|
||||||
builder.read(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_7_REALTIME_STEPS));
|
} catch (IOException ex) {
|
||||||
builder.queue(getQueue());
|
LOG.error("Unable to fetch MI activity data", ex);
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ public abstract class AbstractFetchOperation extends AbstractMiBand2Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
protected void handleActivityFetchFinish() {
|
protected void handleActivityFetchFinish(boolean success) {
|
||||||
operationFinished();
|
operationFinished();
|
||||||
unsetBusy();
|
unsetBusy();
|
||||||
}
|
}
|
||||||
@ -149,18 +149,18 @@ public abstract class AbstractFetchOperation extends AbstractMiBand2Operation {
|
|||||||
DateFormat.getDateTimeInstance().format(startTimestamp.getTime())), Toast.LENGTH_LONG, GB.INFO);
|
DateFormat.getDateTimeInstance().format(startTimestamp.getTime())), Toast.LENGTH_LONG, GB.INFO);
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
} else if (value.length == 3) {
|
} else if (value.length == 3) {
|
||||||
if (Arrays.equals(MiBand2Service.RESPONSE_FINISH_SUCCESS, value)) {
|
if (Arrays.equals(MiBand2Service.RESPONSE_FINISH_SUCCESS, value)) {
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(true);
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
LOG.warn("Unexpected activity metadata: " + Logging.formatBytes(value));
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public class FetchActivityOperation extends AbstractFetchOperation {
|
|||||||
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA});
|
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleActivityFetchFinish() {
|
protected void handleActivityFetchFinish(boolean success) {
|
||||||
LOG.info("Fetching activity data has finished round " + fetchCount);
|
LOG.info("Fetching activity data has finished round " + fetchCount);
|
||||||
GregorianCalendar lastSyncTimestamp = saveSamples();
|
GregorianCalendar lastSyncTimestamp = saveSamples();
|
||||||
if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
|
if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
|
||||||
@ -86,7 +86,7 @@ public class FetchActivityOperation extends AbstractFetchOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.handleActivityFetchFinish();
|
super.handleActivityFetchFinish(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsAnotherFetch(GregorianCalendar lastSyncTimestamp) {
|
private boolean needsAnotherFetch(GregorianCalendar lastSyncTimestamp) {
|
||||||
@ -167,11 +167,12 @@ public class FetchActivityOperation extends AbstractFetchOperation {
|
|||||||
bufferActivityData(value);
|
bufferActivityData(value);
|
||||||
} else {
|
} else {
|
||||||
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
|
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
|
||||||
handleActivityFetchFinish();
|
handleActivityFetchFinish(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GB.toast("Error fetching activity data, unexpected package length: " + value.length, Toast.LENGTH_LONG, GB.ERROR);
|
GB.toast("Error fetching activity data, unexpected package length: " + value.length, Toast.LENGTH_LONG, GB.ERROR);
|
||||||
|
handleActivityFetchFinish(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,174 @@
|
|||||||
|
/* Copyright (C) 2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||||
|
|
||||||
|
This file is part of Gadgetbridge.
|
||||||
|
|
||||||
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Gadgetbridge is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations;
|
||||||
|
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.export.ActivityTrackExporter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.export.GPXExporter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.ActivityDetailsParser;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An operation that fetches activity data. For every fetch, a new operation must
|
||||||
|
* be created, i.e. an operation may not be reused for multiple fetches.
|
||||||
|
*/
|
||||||
|
public class FetchSportsDetailsOperation extends AbstractFetchOperation {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(FetchSportsDetailsOperation.class);
|
||||||
|
private final BaseActivitySummary summary;
|
||||||
|
|
||||||
|
private ByteArrayOutputStream buffer;
|
||||||
|
|
||||||
|
public FetchSportsDetailsOperation(BaseActivitySummary summary, MiBand2Support support) {
|
||||||
|
super(support);
|
||||||
|
this.summary = summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startFetching(TransactionBuilder builder) {
|
||||||
|
buffer = new ByteArrayOutputStream(1024);
|
||||||
|
GregorianCalendar sinceWhen = getLastSuccessfulSyncTime();
|
||||||
|
builder.write(characteristicFetch, BLETypeConversions.join(new byte[] {
|
||||||
|
MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE,
|
||||||
|
AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_DETAILS},
|
||||||
|
getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
|
||||||
|
builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
|
||||||
|
builder.notify(characteristicActivityData, true);
|
||||||
|
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleActivityFetchFinish(boolean success) {
|
||||||
|
LOG.info("Fetching activity data has finished round " + fetchCount);
|
||||||
|
// GregorianCalendar lastSyncTimestamp = saveSamples();
|
||||||
|
// if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
|
||||||
|
// try {
|
||||||
|
// startFetching();
|
||||||
|
// return;
|
||||||
|
// } catch (IOException ex) {
|
||||||
|
// LOG.error("Error starting another round of fetching activity data", ex);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
ActivityDetailsParser parser = new ActivityDetailsParser(summary);
|
||||||
|
parser.setSkipCounterByte(false); // is already stripped
|
||||||
|
try {
|
||||||
|
ActivityTrack track = parser.parse(buffer.toByteArray());
|
||||||
|
ActivityTrackExporter exporter = createExporter();
|
||||||
|
String fileName = FileUtils.makeValidFileName("gadgetbridge-track-" + DateTimeUtils.formatIso8601(summary.getStartTime()));
|
||||||
|
File targetFile = new File(FileUtils.getExternalFilesDir(), fileName);
|
||||||
|
exporter.performExport(track, targetFile);
|
||||||
|
|
||||||
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
|
summary.setGpxTrack(targetFile.getAbsolutePath());
|
||||||
|
dbHandler.getDaoSession().getBaseActivitySummaryDao().update(summary);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
GB.toast(getContext(), "Error getting activity details: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleActivityFetchFinish(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ActivityTrackExporter createExporter() {
|
||||||
|
GPXExporter exporter = new GPXExporter();
|
||||||
|
exporter.setCreator(GBApplication.app().getNameAndVersion());
|
||||||
|
return exporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle the incoming activity data.
|
||||||
|
* There are two kind of messages we currently know:
|
||||||
|
* - the first one is 11 bytes long and contains metadata (how many bytes to expect, when the data starts, etc.)
|
||||||
|
* - the second one is 20 bytes long and contains the actual activity data
|
||||||
|
* <p/>
|
||||||
|
* The first message type is parsed by this method, for every other length of the value param, bufferActivityData is called.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void handleActivityNotif(byte[] value) {
|
||||||
|
LOG.warn("sports data: " + Logging.formatBytes(value));
|
||||||
|
|
||||||
|
if (!isOperationRunning()) {
|
||||||
|
LOG.error("ignoring activity data notification because operation is not running. Data length: " + value.length);
|
||||||
|
getSupport().logMessageContent(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.length < 2) {
|
||||||
|
LOG.error("unexpected sports summary data length: " + value.length);
|
||||||
|
getSupport().logMessageContent(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((byte) (lastPacketCounter + 1) == value[0] ) {
|
||||||
|
lastPacketCounter++;
|
||||||
|
bufferActivityData(value);
|
||||||
|
} else {
|
||||||
|
GB.toast("Error fetching activity data, invalid package counter: " + value[0] + ", last was: " + lastPacketCounter, Toast.LENGTH_LONG, GB.ERROR);
|
||||||
|
handleActivityFetchFinish(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffers the given activity summary data. If the total size is reached,
|
||||||
|
* it is converted to an object and saved in the database.
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void bufferActivityData(byte[] value) {
|
||||||
|
buffer.write(value, 1, value.length - 1); // skip the counter
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getLastSyncTimeKey() {
|
||||||
|
return getDevice().getAddress() + "_" + "lastSportsSummaryTimeMillis";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GregorianCalendar getLastSuccessfulSyncTime() {
|
||||||
|
// FIXME: remove this!
|
||||||
|
GregorianCalendar calendar = BLETypeConversions.createCalendar();
|
||||||
|
calendar.setTime(summary.getStartTime());
|
||||||
|
return calendar;
|
||||||
|
}
|
||||||
|
}
|
@ -23,12 +23,30 @@ import android.widget.Toast;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
import nodomain.freeyourgadget.gadgetbridge.Logging;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.miband2.MiBand2Const;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
@ -39,9 +57,9 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
|||||||
public class FetchSportsSummaryOperation extends AbstractFetchOperation {
|
public class FetchSportsSummaryOperation extends AbstractFetchOperation {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(FetchSportsSummaryOperation.class);
|
private static final Logger LOG = LoggerFactory.getLogger(FetchSportsSummaryOperation.class);
|
||||||
|
|
||||||
// private List<MiBandActivitySample> samples = new ArrayList<>(60*24); // 1day per default
|
private ByteArrayOutputStream buffer = new ByteArrayOutputStream(140);
|
||||||
|
|
||||||
private byte lastPacketCounter;
|
// private List<MiBandActivitySample> samples = new ArrayList<>(60*24); // 1day per default
|
||||||
|
|
||||||
public FetchSportsSummaryOperation(MiBand2Support support) {
|
public FetchSportsSummaryOperation(MiBand2Support support) {
|
||||||
super(support);
|
super(support);
|
||||||
@ -50,18 +68,19 @@ public class FetchSportsSummaryOperation extends AbstractFetchOperation {
|
|||||||
@Override
|
@Override
|
||||||
protected void startFetching(TransactionBuilder builder) {
|
protected void startFetching(TransactionBuilder builder) {
|
||||||
GregorianCalendar sinceWhen = getLastSuccessfulSyncTime();
|
GregorianCalendar sinceWhen = getLastSuccessfulSyncTime();
|
||||||
// builder.write(characteristicFetch, BLETypeConversions.join(new byte[] {
|
builder.write(characteristicFetch, BLETypeConversions.join(new byte[] {
|
||||||
// MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE,
|
MiBand2Service.COMMAND_ACTIVITY_DATA_START_DATE,
|
||||||
// AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES},
|
AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES},
|
||||||
// getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
|
getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)));
|
||||||
// builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
|
builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply
|
||||||
// builder.notify(characteristicActivityData, true);
|
builder.notify(characteristicActivityData, true);
|
||||||
// builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA });
|
builder.write(characteristicFetch, new byte[] { MiBand2Service.COMMAND_FETCH_DATA });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleActivityFetchFinish() {
|
protected void handleActivityFetchFinish(boolean success) {
|
||||||
LOG.info("Fetching activity data has finished round " + fetchCount);
|
LOG.info("Fetching activity data has finished round " + fetchCount);
|
||||||
|
|
||||||
// GregorianCalendar lastSyncTimestamp = saveSamples();
|
// GregorianCalendar lastSyncTimestamp = saveSamples();
|
||||||
// if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
|
// if (lastSyncTimestamp != null && needsAnotherFetch(lastSyncTimestamp)) {
|
||||||
// try {
|
// try {
|
||||||
@ -72,7 +91,31 @@ public class FetchSportsSummaryOperation extends AbstractFetchOperation {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
super.handleActivityFetchFinish();
|
BaseActivitySummary summary = null;
|
||||||
|
if (success) {
|
||||||
|
summary = parseSummary(buffer);
|
||||||
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
|
DaoSession session = dbHandler.getDaoSession();
|
||||||
|
Device device = DBHelper.getDevice(getDevice(), session);
|
||||||
|
User user = DBHelper.getUser(session);
|
||||||
|
summary.setDevice(device);
|
||||||
|
summary.setUser(user);
|
||||||
|
session.getBaseActivitySummaryDao().insertOrReplace(summary);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
GB.toast(getContext(), "Error saving activity summary", Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleActivityFetchFinish(success);
|
||||||
|
|
||||||
|
if (summary != null) {
|
||||||
|
FetchSportsDetailsOperation nextOperation = new FetchSportsDetailsOperation(summary, getSupport());
|
||||||
|
try {
|
||||||
|
nextOperation.perform();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
GB.toast(getContext(), "Unable to fetch activity details: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -101,48 +144,103 @@ public class FetchSportsSummaryOperation extends AbstractFetchOperation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((value.length % 4) == 1) {
|
if (value.length < 2) {
|
||||||
if ((byte) (lastPacketCounter + 1) == value[0] ) {
|
LOG.error("unexpected sports summary data length: " + value.length);
|
||||||
lastPacketCounter++;
|
getSupport().logMessageContent(value);
|
||||||
bufferActivityData(value);
|
return;
|
||||||
} else {
|
}
|
||||||
GB.toast("Error fetching activity data, invalid package counter: " + value[0], Toast.LENGTH_LONG, GB.ERROR);
|
|
||||||
handleActivityFetchFinish();
|
if ((byte) (lastPacketCounter + 1) == value[0] ) {
|
||||||
return;
|
lastPacketCounter++;
|
||||||
}
|
bufferActivityData(value);
|
||||||
} else {
|
} else {
|
||||||
GB.toast("Error fetching activity data, unexpected package length: " + value.length, Toast.LENGTH_LONG, GB.ERROR);
|
GB.toast("Error fetching activity data, invalid package counter: " + value[0] + ", last was: " + lastPacketCounter, Toast.LENGTH_LONG, GB.ERROR);
|
||||||
LOG.warn("Unexpected activity data: " + Logging.formatBytes(value));
|
handleActivityFetchFinish(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates samples from the given 17-length array
|
* Buffers the given activity summary data. If the total size is reached,
|
||||||
|
* it is converted to an object and saved in the database.
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void bufferActivityData(byte[] value) {
|
protected void bufferActivityData(byte[] value) {
|
||||||
// TODO: implement
|
buffer.write(value, 1, value.length - 1); // skip the counter
|
||||||
// int len = value.length;
|
}
|
||||||
|
|
||||||
|
private BaseActivitySummary parseSummary(ByteArrayOutputStream stream) {
|
||||||
|
BaseActivitySummary summary = new BaseActivitySummary();
|
||||||
|
ByteBuffer buffer = ByteBuffer.wrap(stream.toByteArray()).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
// summary.setVersion(BLETypeConversions.toUnsigned(buffer.getShort()));
|
||||||
|
buffer.getShort(); // version
|
||||||
|
int rawKind = BLETypeConversions.toUnsigned(buffer.getShort());
|
||||||
|
int activityKind = MiBand2Const.toActivityKind(rawKind);
|
||||||
|
if (activityKind == ActivityKind.TYPE_UNKNOWN) {
|
||||||
|
activityKind = rawKind; // hack for later activity kind detection
|
||||||
|
}
|
||||||
|
summary.setActivityKind(activityKind);
|
||||||
|
// FIXME: should save timezone etc.
|
||||||
|
summary.setStartTime(new Date(BLETypeConversions.toUnsigned(buffer.getInt()) * 1000));
|
||||||
|
summary.setEndTime(new Date(BLETypeConversions.toUnsigned(buffer.getInt()) * 1000));
|
||||||
|
int baseLongitude = buffer.getInt();
|
||||||
|
int baseLatitude = buffer.getInt();
|
||||||
|
int baseAltitude = buffer.getInt();
|
||||||
|
summary.setBaseLongitude(baseLongitude);
|
||||||
|
summary.setBaseLatitude(baseLatitude);
|
||||||
|
summary.setBaseAltitude(baseAltitude);
|
||||||
|
// summary.setBaseCoordinate(new GPSCoordinate(baseLatitude, baseLongitude, baseAltitude));
|
||||||
|
|
||||||
|
// summary.setDistanceMeters(Float.intBitsToFloat(buffer.getInt()));
|
||||||
|
// summary.setAscentMeters(Float.intBitsToFloat(buffer.getInt()));
|
||||||
|
// summary.setDescentMeters(Float.intBitsToFloat(buffer.getInt()));
|
||||||
//
|
//
|
||||||
// if (len % 4 != 1) {
|
// summary.setMinAltitude(Float.intBitsToFloat(buffer.getInt()));
|
||||||
// throw new AssertionError("Unexpected activity array size: " + len);
|
// summary.setMaxAltitude(Float.intBitsToFloat(buffer.getInt()));
|
||||||
// }
|
// summary.setMinLatitude(buffer.getInt());
|
||||||
|
// summary.setMaxLatitude(buffer.getInt());
|
||||||
|
// summary.setMinLongitude(buffer.getInt());
|
||||||
|
// summary.setMaxLongitude(buffer.getInt());
|
||||||
//
|
//
|
||||||
// for (int i = 1; i < len; i+=4) {
|
// summary.setSteps(BLETypeConversions.toUnsigned(buffer.getInt()));
|
||||||
// }
|
// summary.setActiveTimeSeconds(BLETypeConversions.toUnsigned(buffer.getInt()));
|
||||||
|
//
|
||||||
|
// summary.setCaloriesBurnt(Float.intBitsToFloat(buffer.get()));
|
||||||
|
// summary.setMaxSpeed(Float.intBitsToFloat(buffer.get()));
|
||||||
|
// summary.setMinPace(Float.intBitsToFloat(buffer.get()));
|
||||||
|
// summary.setMaxPace(Float.intBitsToFloat(buffer.get()));
|
||||||
|
// summary.setTotalStride(Float.intBitsToFloat(buffer.get()));
|
||||||
|
|
||||||
|
buffer.getInt(); //
|
||||||
|
buffer.getInt(); //
|
||||||
|
buffer.getInt(); //
|
||||||
|
|
||||||
|
// summary.setTimeAscent(BLETypeConversions.toUnsigned(buffer.getInt()));
|
||||||
|
// buffer.getInt(); //
|
||||||
|
// summary.setTimeDescent(BLETypeConversions.toUnsigned(buffer.getInt()));
|
||||||
|
// buffer.getInt(); //
|
||||||
|
// summary.setTimeFlat(BLETypeConversions.toUnsigned(buffer.getInt()));
|
||||||
|
//
|
||||||
|
// summary.setAverageHR(BLETypeConversions.toUnsigned(buffer.getShort()));
|
||||||
|
//
|
||||||
|
// summary.setAveragePace(BLETypeConversions.toUnsigned(buffer.getShort()));
|
||||||
|
// summary.setAverageStride(BLETypeConversions.toUnsigned(buffer.getShort()));
|
||||||
|
|
||||||
|
buffer.getShort(); //
|
||||||
|
|
||||||
|
return summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getLastSyncTimeKey() {
|
protected String getLastSyncTimeKey() {
|
||||||
return getDevice().getAddress() + "_" + "lastSportsSyncTimeMillis";
|
return getDevice().getAddress() + "_" + "lastSportsSummaryTimeMillis";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected GregorianCalendar getLastSuccessfulSyncTime() {
|
protected GregorianCalendar getLastSuccessfulSyncTime() {
|
||||||
// FIXME: remove this!
|
// FIXME: remove this!
|
||||||
GregorianCalendar calendar = BLETypeConversions.createCalendar();
|
GregorianCalendar calendar = BLETypeConversions.createCalendar();
|
||||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
calendar.add(Calendar.DAY_OF_MONTH, -25);
|
||||||
return calendar;
|
return calendar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,36 @@ package nodomain.freeyourgadget.gadgetbridge.util;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.support.v4.content.FileProvider;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.activities.ActivitySummariesActivity;
|
||||||
|
|
||||||
public class AndroidUtils {
|
public class AndroidUtils {
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ParcelUuid} array with the contents of the given uuids.
|
||||||
|
* The given array is expected to contain only {@link ParcelUuid} elements.
|
||||||
|
* @param uuids an array of {@link ParcelUuid} elements
|
||||||
|
* @return a {@link ParcelUuid} array instance with the same contents
|
||||||
|
*/
|
||||||
public static ParcelUuid[] toParcelUUids(Parcelable[] uuids) {
|
public static ParcelUuid[] toParcelUUids(Parcelable[] uuids) {
|
||||||
if (uuids == null) {
|
if (uuids == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ParcelUuid[] uuids2 = new ParcelUuid[uuids.length];
|
ParcelUuid[] uuids2 = new ParcelUuid[uuids.length];
|
||||||
|
//noinspection SuspiciousSystemArraycopy
|
||||||
System.arraycopy(uuids, 0, uuids2, 0, uuids.length);
|
System.arraycopy(uuids, 0, uuids2, 0, uuids.length);
|
||||||
return uuids2;
|
return uuids2;
|
||||||
}
|
}
|
||||||
@ -112,4 +125,15 @@ public class AndroidUtils {
|
|||||||
+ Integer.toHexString(Color.green(color))
|
+ Integer.toHexString(Color.green(color))
|
||||||
+ Integer.toHexString(Color.blue(color));
|
+ Integer.toHexString(Color.blue(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void viewFile(String path, String action, Context context) throws IOException {
|
||||||
|
Intent intent = new Intent(action);
|
||||||
|
File file = new File(path);
|
||||||
|
|
||||||
|
Uri contentUri = FileProvider.getUriForFile(context,
|
||||||
|
context.getApplicationContext().getPackageName() + ".screenshot_provider", file);
|
||||||
|
intent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
intent.setData(contentUri);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,14 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
|||||||
|
|
||||||
public class DateTimeUtils {
|
public class DateTimeUtils {
|
||||||
private static SimpleDateFormat DAY_STORAGE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
private static SimpleDateFormat DAY_STORAGE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||||
|
public static SimpleDateFormat ISO_8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ssXXX", Locale.US);
|
||||||
|
|
||||||
public static String formatDateTime(Date date) {
|
public static String formatDateTime(Date date) {
|
||||||
return DateUtils.formatDateTime(GBApplication.getContext(), date.getTime(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME);
|
return DateUtils.formatDateTime(GBApplication.getContext(), date.getTime(), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_NO_YEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatIso8601(Date date) {
|
||||||
|
return ISO_8601_FORMAT.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String formatDate(Date date) {
|
public static String formatDate(Date date) {
|
||||||
|
@ -272,4 +272,14 @@ public class FileUtils {
|
|||||||
}
|
}
|
||||||
throw new IOException("Cannot create temporary directory in " + parent);
|
throw new IOException("Cannot create temporary directory in " + parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces some wellknown invalid characters in the given filename
|
||||||
|
* to underscrores.
|
||||||
|
* @param name the file name to make valid
|
||||||
|
* @return the valid file name
|
||||||
|
*/
|
||||||
|
public static String makeValidFileName(String name) {
|
||||||
|
return name.replaceAll("\0/:\\r\\n\\\\", "_");
|
||||||
|
}
|
||||||
}
|
}
|
7
app/src/main/res/drawable/ic_activity_biking.xml
Normal file
7
app/src/main/res/drawable/ic_activity_biking.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M5,20.5A3.5,3.5 0 0,1 1.5,17A3.5,3.5 0 0,1 5,13.5A3.5,3.5 0 0,1 8.5,17A3.5,3.5 0 0,1 5,20.5M5,12A5,5 0 0,0 0,17A5,5 0 0,0 5,22A5,5 0 0,0 10,17A5,5 0 0,0 5,12M14.8,10H19V8.2H15.8L13.86,4.93C13.57,4.43 13,4.1 12.4,4.1C11.93,4.1 11.5,4.29 11.2,4.6L7.5,8.29C7.19,8.6 7,9 7,9.5C7,10.13 7.33,10.66 7.85,10.97L11.2,13V18H13V11.5L10.75,9.85L13.07,7.5M19,20.5A3.5,3.5 0 0,1 15.5,17A3.5,3.5 0 0,1 19,13.5A3.5,3.5 0 0,1 22.5,17A3.5,3.5 0 0,1 19,20.5M19,12A5,5 0 0,0 14,17A5,5 0 0,0 19,22A5,5 0 0,0 24,17A5,5 0 0,0 19,12M16,4.8C17,4.8 17.8,4 17.8,3C17.8,2 17,1.2 16,1.2C15,1.2 14.2,2 14.2,3C14.2,4 15,4.8 16,4.8Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_deep_sleep.xml
Normal file
7
app/src/main/res/drawable/ic_activity_deep_sleep.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M23,12H17V10L20.39,6H17V4H23V6L19.62,10H23V12M15,16H9V14L12.39,10H9V8H15V10L11.62,14H15V16M7,20H1V18L4.39,14H1V12H7V14L3.62,18H7V20Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_light_sleep.xml
Normal file
7
app/src/main/res/drawable/ic_activity_light_sleep.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M23,12H17V10L20.39,6H17V4H23V6L19.62,10H23V12M15,16H9V14L12.39,10H9V8H15V10L11.62,14H15V16M7,20H1V18L4.39,14H1V12H7V14L3.62,18H7V20Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_not_measured.xml
Normal file
7
app/src/main/res/drawable/ic_activity_not_measured.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M12,20A7,7 0 0,1 5,13C5,11.72 5.35,10.5 5.95,9.5L15.5,19.04C14.5,19.65 13.28,20 12,20M3,4L1.75,5.27L4.5,8.03C3.55,9.45 3,11.16 3,13A9,9 0 0,0 12,22C13.84,22 15.55,21.45 17,20.5L19.5,23L20.75,21.73L13.04,14L3,4M11,9.44L13,11.44V8H11M15,1H9V3H15M19.04,4.55L17.62,5.97C16.07,4.74 14.12,4 12,4C10.17,4 8.47,4.55 7.05,5.5L8.5,6.94C9.53,6.35 10.73,6 12,6A7,7 0 0,1 19,13C19,14.27 18.65,15.47 18.06,16.5L19.5,17.94C20.45,16.53 21,14.83 21,13C21,10.88 20.26,8.93 19.03,7.39L20.45,5.97L19.04,4.55Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_running.xml
Normal file
7
app/src/main/res/drawable/ic_activity_running.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M13.5,5.5C14.59,5.5 15.5,4.58 15.5,3.5C15.5,2.38 14.59,1.5 13.5,1.5C12.39,1.5 11.5,2.38 11.5,3.5C11.5,4.58 12.39,5.5 13.5,5.5M9.89,19.38L10.89,15L13,17V23H15V15.5L12.89,13.5L13.5,10.5C14.79,12 16.79,13 19,13V11C17.09,11 15.5,10 14.69,8.58L13.69,7C13.29,6.38 12.69,6 12,6C11.69,6 11.5,6.08 11.19,6.08L6,8.28V13H8V9.58L9.79,8.88L8.19,17L3.29,16L2.89,18L9.89,19.38Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_tracks.xml
Normal file
7
app/src/main/res/drawable/ic_activity_tracks.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M13.5,5.5C14.59,5.5 15.5,4.58 15.5,3.5C15.5,2.38 14.59,1.5 13.5,1.5C12.39,1.5 11.5,2.38 11.5,3.5C11.5,4.58 12.39,5.5 13.5,5.5M9.89,19.38L10.89,15L13,17V23H15V15.5L12.89,13.5L13.5,10.5C14.79,12 16.79,13 19,13V11C17.09,11 15.5,10 14.69,8.58L13.69,7C13.29,6.38 12.69,6 12,6C11.69,6 11.5,6.08 11.19,6.08L6,8.28V13H8V9.58L9.79,8.88L8.19,17L3.29,16L2.89,18L9.89,19.38Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_unknown.xml
Normal file
7
app/src/main/res/drawable/ic_activity_unknown.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z" />
|
||||||
|
</vector>
|
7
app/src/main/res/drawable/ic_activity_walking.xml
Normal file
7
app/src/main/res/drawable/ic_activity_walking.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#000" android:pathData="M14.12,10H19V8.2H15.38L13.38,4.87C13.08,4.37 12.54,4.03 11.92,4.03C11.74,4.03 11.58,4.06 11.42,4.11L6,5.8V11H7.8V7.33L9.91,6.67L6,22H7.8L10.67,13.89L13,17V22H14.8V15.59L12.31,11.05L13.04,8.18M14,3.8C15,3.8 15.8,3 15.8,2C15.8,1 15,0.2 14,0.2C13,0.2 12.2,1 12.2,2C12.2,3 13,3.8 14,3.8Z" />
|
||||||
|
</vector>
|
12
app/src/main/res/layout/activity_list.xml
Normal file
12
app/src/main/res/layout/activity_list.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/itemListView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="false"></ListView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -231,12 +231,27 @@
|
|||||||
card_view:srcCompat="@drawable/ic_activity_graphs" />
|
card_view:srcCompat="@drawable/ic_activity_graphs" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/device_action_find"
|
android:id="@+id/device_action_show_activity_tracks"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_below="@id/device_image"
|
android:layout_below="@id/device_image"
|
||||||
android:layout_margin="4dp"
|
android:layout_margin="4dp"
|
||||||
android:layout_toEndOf="@id/device_action_show_activity_graphs"
|
android:layout_toEndOf="@id/device_action_show_activity_graphs"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="@string/controlcenter_start_activity_tracks"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:tint="@color/secondarytext"
|
||||||
|
card_view:srcCompat="@drawable/ic_activity_tracks" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/device_action_find"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_below="@id/device_image"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:layout_toEndOf="@id/device_action_show_activity_tracks"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:contentDescription="@string/controlcenter_find_device"
|
android:contentDescription="@string/controlcenter_find_device"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
|
@ -483,4 +483,16 @@
|
|||||||
<string name="_pebble_watch_open_on_phone">Open on phone</string>
|
<string name="_pebble_watch_open_on_phone">Open on phone</string>
|
||||||
<string name="_pebble_watch_mute">Mute</string>
|
<string name="_pebble_watch_mute">Mute</string>
|
||||||
<string name="_pebble_watch_reply">Reply</string>
|
<string name="_pebble_watch_reply">Reply</string>
|
||||||
|
<string name="controlcenter_start_activity_tracks">Your activity tracks</string>
|
||||||
|
<string name="activity_type_not_measured">Not measured</string>
|
||||||
|
<string name="activity_type_activity">Activity</string>
|
||||||
|
<string name="activity_type_light_sleep">Light sleep</string>
|
||||||
|
<string name="activity_type_deep_sleep">Deep sleep</string>
|
||||||
|
<string name="activity_type_not_worn">Device not worn</string>
|
||||||
|
<string name="activity_type_running">Running</string>
|
||||||
|
<string name="activity_type_walking">Walking</string>
|
||||||
|
<string name="activity_type_swimming">Swimming</string>
|
||||||
|
<string name="activity_type_unknown">Unknown activity</string>
|
||||||
|
<string name="activity_summaries">Activities</string>
|
||||||
|
<string name="activity_type_biking">Biking</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- defines directories shared to other applications -->
|
||||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<external-path name="external_files" path="."/>
|
<external-path name="external_files" path="."/>
|
||||||
|
<files-path name="gpx" path="./"/>
|
||||||
</paths>
|
</paths>
|
@ -0,0 +1,110 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.amazfitbip.BipActivitySummary;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.export.GPXExporter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.ActivityDetailsParser;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class ActivityDetailsParserTest extends TestBase {
|
||||||
|
private static final URL DETAILS_1 = ActivityDetailsParserTest.class.getClassLoader().getResource("ActivityDetailsDump1.txt");
|
||||||
|
private static final long MAX_DETAILS = 1024 * 1024;
|
||||||
|
private static Date baseTime;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpSuite() throws Exception {
|
||||||
|
baseTime = DateTimeUtils.ISO_8601_FORMAT.parse("2017-01-20T14:00:00-00:00"); // yyyy-mm-dd'T'hh:mm:ssZ
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testActivityDetails() throws Exception {
|
||||||
|
BipActivitySummary summary = createSummary();
|
||||||
|
|
||||||
|
ActivityDetailsParser parser = new ActivityDetailsParser(summary);
|
||||||
|
parser.setSkipCounterByte(true);
|
||||||
|
try (InputStream in = getContents(DETAILS_1)) {
|
||||||
|
ActivityTrack track = parser.parse(FileUtils.readAll(in, MAX_DETAILS));
|
||||||
|
assertEquals("SuperBand 2000", track.getDevice().getName());
|
||||||
|
assertEquals("Elvis", track.getUser().getName());
|
||||||
|
|
||||||
|
List<ActivityPoint> trackPoints = track.getTrackPoints();
|
||||||
|
assertEquals(1208, trackPoints.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BipActivitySummary createSummary() {
|
||||||
|
BipActivitySummary summary = new BipActivitySummary();
|
||||||
|
summary.setBaseLongitude(1);
|
||||||
|
summary.setBaseLatitude(1);
|
||||||
|
summary.setBaseAltitude(1);
|
||||||
|
summary.setStartTime(baseTime);
|
||||||
|
User dummyUser = new User(0L);
|
||||||
|
dummyUser.setName("Elvis");
|
||||||
|
summary.setName("testtrack");
|
||||||
|
summary.setUser(dummyUser);
|
||||||
|
Device device = new Device(0l);
|
||||||
|
device.setName("SuperBand 2000");
|
||||||
|
summary.setDevice(device);
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGPXExport() throws Exception {
|
||||||
|
BipActivitySummary summary = createSummary();
|
||||||
|
|
||||||
|
int baseLongi = BLETypeConversions.toUint32((byte) 0xd6, (byte) 0xc4,(byte) 0x62,(byte) 0x02);
|
||||||
|
int baseLati = BLETypeConversions.toUint32((byte) 0xff, (byte) 0xa9, (byte) 0x61, (byte) 0x9);
|
||||||
|
int baseAlti = BLETypeConversions.toUint32((byte) 0x30, (byte) 0x0, (byte) 0x0, (byte) 0x0);
|
||||||
|
|
||||||
|
summary.setBaseLongitude(baseLongi);
|
||||||
|
summary.setBaseLatitude(baseLati);
|
||||||
|
summary.setBaseAltitude(baseAlti);
|
||||||
|
|
||||||
|
ActivityDetailsParser parser = new ActivityDetailsParser(summary);
|
||||||
|
parser.setSkipCounterByte(true);
|
||||||
|
try (InputStream in = getContents(DETAILS_1)) {
|
||||||
|
ActivityTrack track = parser.parse(FileUtils.readAll(in, MAX_DETAILS));
|
||||||
|
|
||||||
|
List<ActivityPoint> trackPoints = track.getTrackPoints();
|
||||||
|
assertEquals(1208, trackPoints.size());
|
||||||
|
|
||||||
|
|
||||||
|
GPXExporter exporter = new GPXExporter();
|
||||||
|
exporter.setIncludeHeartRate(false);
|
||||||
|
exporter.setCreator(getClass().getName());
|
||||||
|
File targetFile = File.createTempFile("gadgetbridge-track", ".gpx");
|
||||||
|
System.out.println("Writing GPX file: " + targetFile);
|
||||||
|
exporter.performExport(track, targetFile);
|
||||||
|
|
||||||
|
assertTrue(targetFile.length() > 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getContents(URL hexFile) throws IOException {
|
||||||
|
return new HexToBinaryInputStream(hexFile.openStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
class HexToBinaryInputStream extends FilterInputStream {
|
||||||
|
HexToBinaryInputStream(InputStream in) {
|
||||||
|
super(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
int value;
|
||||||
|
StringBuilder buffer = new StringBuilder(4);
|
||||||
|
|
||||||
|
loop:
|
||||||
|
while (true) {
|
||||||
|
value = super.read();
|
||||||
|
switch (value) {
|
||||||
|
case -1:
|
||||||
|
case ' ':
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
break loop;
|
||||||
|
default:
|
||||||
|
buffer.append((char) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer.length() > 0) {
|
||||||
|
return Integer.decode(buffer.toString());
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(@NonNull byte[] b, int off, int len) throws IOException {
|
||||||
|
if (off < 0 || len < 0 || len > b.length - off) {
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
int value = read();
|
||||||
|
if (value == -1) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
b[off + i] = (byte) value;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.test;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class HexToBinaryInputStreamTest extends TestBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConversion() throws IOException {
|
||||||
|
byte[] hexString;
|
||||||
|
byte[] binString;
|
||||||
|
|
||||||
|
try (InputStream in = ActivityDetailsParserTest.class.getClassLoader().getResourceAsStream("ActivityDetailsDump1.txt")) {
|
||||||
|
hexString = FileUtils.readAll(in, 1024 * 1024);
|
||||||
|
assertTrue(hexString.length > 1);
|
||||||
|
try (InputStream in2 = getContents(ActivityDetailsParserTest.class.getClassLoader().getResource("ActivityDetailsDump1.txt"))) {
|
||||||
|
binString = FileUtils.readAll(in2, 1024 * 1024);
|
||||||
|
assertTrue(binString.length > 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertTrue(hexString.length > binString.length);
|
||||||
|
ByteArrayOutputStream binToHexOut = new ByteArrayOutputStream(hexString.length);
|
||||||
|
for (int i = 0; i < binString.length; i++) {
|
||||||
|
String hexed = String.format("0x%x", binString[i]);
|
||||||
|
binToHexOut.write(hexed.getBytes("US-ASCII"));
|
||||||
|
if ((i + 1) % 17 == 0) {
|
||||||
|
binToHexOut.write('\n');
|
||||||
|
} else {
|
||||||
|
binToHexOut.write(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] hexedBytes = binToHexOut.toByteArray();
|
||||||
|
Assert.assertArrayEquals(hexString, hexedBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getContents(URL hexFile) throws IOException {
|
||||||
|
return new HexToBinaryInputStream(hexFile.openStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
861
app/src/test/resources/ActivityDetailsDump1.txt
Normal file
861
app/src/test/resources/ActivityDetailsDump1.txt
Normal file
@ -0,0 +1,861 @@
|
|||||||
|
0x0 0x1 0x7 0x47 0x0 0x0 0x0 0x0 0x0 0x1 0x8 0x46 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1 0x1 0xa 0x43 0x0 0x0 0x0 0x0 0x0 0x1 0xc 0x46 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2 0x1 0xd 0x44 0x0 0x0 0x0 0x0 0x0 0x1 0xf 0x3e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3 0x1 0x11 0x3b 0x0 0x0 0x0 0x0 0x0 0x1 0x12 0x3e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4 0x1 0x17 0x3d 0x0 0x0 0x0 0x0 0x0 0x1 0x18 0x3f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5 0x1 0x1b 0x41 0x0 0x0 0x0 0x0 0x0 0x1 0x1d 0x42 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6 0x1 0x20 0x43 0x0 0x0 0x0 0x0 0x0 0x1 0x21 0x44 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7 0x1 0x22 0x45 0x0 0x0 0x0 0x0 0x0 0x0 0x23 0x0 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8 0x0 0x23 0x79 0xff 0xcd 0x0 0x0 0x0 0x0 0x23 0x88 0xff 0xc3 0x0 0x0 0x0
|
||||||
|
0x9 0x0 0x23 0xbf 0xff 0xeb 0x0 0x0 0x0 0x0 0x23 0xec 0xff 0x4 0x1 0x0 0x0
|
||||||
|
0xa 0x0 0x23 0x5 0x0 0x4 0x1 0x0 0x0 0x0 0x23 0xf6 0xff 0x4f 0x1 0x0 0x0
|
||||||
|
0xb 0x0 0x23 0xec 0xff 0x18 0x1 0x0 0x0 0x0 0x23 0xf1 0xff 0xff 0x0 0x0 0x0
|
||||||
|
0xc 0x0 0x23 0xf1 0xff 0xf5 0x0 0x0 0x0 0x0 0x23 0xe2 0xff 0xa0 0x0 0x0 0x0
|
||||||
|
0xd 0x0 0x23 0x9c 0xff 0xeb 0x0 0x0 0x0 0x0 0x23 0xf1 0xff 0xeb 0x0 0x0 0x0
|
||||||
|
0xe 0x0 0x23 0xfb 0xff 0xe 0x1 0x0 0x0 0x0 0x23 0xf6 0xff 0x13 0x1 0x0 0x0
|
||||||
|
0xf 0x0 0x23 0xfb 0xff 0x68 0x1 0x0 0x0 0x0 0x23 0xe2 0xff 0x18 0x1 0x0 0x0
|
||||||
|
0x10 0x0 0x23 0xb5 0xff 0xd2 0x0 0x0 0x0 0x0 0x23 0x97 0xff 0x87 0x0 0x0 0x0
|
||||||
|
0x11 0x0 0x23 0xba 0xff 0xa5 0x0 0x0 0x0 0x0 0x23 0xe2 0xff 0xfa 0x0 0x0 0x0
|
||||||
|
0x12 0x0 0x23 0xe2 0xff 0xb9 0x0 0x0 0x0 0x0 0x23 0xfb 0xff 0x4 0x1 0x0 0x0
|
||||||
|
0x13 0x0 0x23 0xec 0xff 0xa5 0x0 0x0 0x0 0x0 0x23 0xf1 0xff 0x2c 0x1 0x0 0x0
|
||||||
|
0x14 0x0 0x23 0x5 0x0 0xe 0x1 0x0 0x0 0x0 0x23 0xec 0xff 0x9b 0x0 0x0 0x0
|
||||||
|
0x15 0x0 0x23 0xf1 0xff 0xa5 0x0 0x0 0x0 0x0 0x23 0xf6 0xff 0xb4 0x0 0x0 0x0
|
||||||
|
0x16 0x0 0x23 0xec 0xff 0xc3 0x0 0x0 0x0 0x0 0x23 0x7e 0xff 0xd2 0x0 0x0 0x0
|
||||||
|
0x17 0x6 0x23 0x81 0x0 0xd2 0x0 0x0 0x0 0x0 0x24 0xd3 0xff 0x7d 0x0 0x0 0x0
|
||||||
|
0x18 0x6 0x24 0x81 0x0 0x7d 0x0 0x0 0x0 0x0 0x25 0xc1 0xff 0xb1 0x0 0x0 0x0
|
||||||
|
0x19 0x6 0x25 0x81 0x0 0xb1 0x0 0x0 0x0 0x0 0x26 0xca 0xff 0xc9 0x0 0x0 0x0
|
||||||
|
0x1a 0x6 0x26 0x81 0x0 0xc9 0x0 0x0 0x0 0x0 0x27 0xd7 0xff 0xdd 0x0 0x0 0x0
|
||||||
|
0x1b 0x6 0x27 0x81 0x0 0xdd 0x0 0x0 0x0 0x1 0x27 0x46 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1c 0x0 0x28 0xe4 0xff 0xf8 0x0 0x0 0x0 0x6 0x28 0x81 0x0 0xf8 0x0 0x0 0x0
|
||||||
|
0x1d 0x0 0x29 0xef 0xff 0xf 0x1 0x0 0x0 0x6 0x29 0x81 0x0 0xf 0x1 0x0 0x0
|
||||||
|
0x1e 0x1 0x29 0x43 0x0 0x0 0x0 0x0 0x0 0x0 0x2a 0xf1 0xff 0x2 0x1 0x0 0x0
|
||||||
|
0x1f 0x6 0x2a 0x81 0x0 0x2 0x1 0x0 0x0 0x1 0x2a 0x45 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x20 0x0 0x2b 0xeb 0xff 0xf4 0x0 0xfe 0xff 0x6 0x2b 0x81 0x0 0xf4 0x0 0xfe 0xff
|
||||||
|
0x21 0x0 0x2c 0xe8 0xff 0xdc 0x0 0x0 0x0 0x6 0x2c 0x81 0x0 0xdc 0x0 0x0 0x0
|
||||||
|
0x22 0x0 0x2d 0xe9 0xff 0xca 0x0 0x0 0x0 0x6 0x2d 0x81 0x0 0xca 0x0 0x0 0x0
|
||||||
|
0x23 0x0 0x2e 0xeb 0xff 0xc9 0x0 0x0 0x0 0x6 0x2e 0x81 0x0 0xc9 0x0 0x0 0x0
|
||||||
|
0x24 0x1 0x2e 0x46 0x0 0x0 0x0 0x0 0x0 0x0 0x2f 0xed 0xff 0xcb 0x0 0x0 0x0
|
||||||
|
0x25 0x6 0x2f 0x81 0x0 0xcb 0x0 0x0 0x0 0x1 0x2f 0x47 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x26 0x0 0x30 0xf0 0xff 0xc5 0x0 0x0 0x0 0x6 0x30 0x81 0x0 0xc5 0x0 0x0 0x0
|
||||||
|
0x27 0x0 0x31 0xf2 0xff 0xb7 0x0 0x0 0x0 0x6 0x31 0x81 0x0 0xb7 0x0 0x0 0x0
|
||||||
|
0x28 0x0 0x32 0xf1 0xff 0xb1 0x0 0x0 0x0 0x6 0x32 0x81 0x0 0xb1 0x0 0x0 0x0
|
||||||
|
0x29 0x0 0x33 0xf7 0xff 0xb5 0x0 0x0 0x0 0x6 0x33 0x81 0x0 0xb5 0x0 0x0 0x0
|
||||||
|
0x2a 0x1 0x33 0x49 0x0 0x0 0x0 0x0 0x0 0x0 0x34 0xfa 0xff 0xc8 0x0 0x0 0x0
|
||||||
|
0x2b 0x6 0x34 0x81 0x0 0xc8 0x0 0x0 0x0 0x1 0x34 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2c 0x0 0x35 0xf7 0xff 0xda 0x0 0x0 0x0 0x6 0x35 0x81 0x0 0xda 0x0 0x0 0x0
|
||||||
|
0x2d 0x1 0x35 0x4b 0x0 0x0 0x0 0x0 0x0 0x0 0x36 0xf3 0xff 0xdb 0x0 0x0 0x0
|
||||||
|
0x2e 0x6 0x36 0x81 0x0 0xdb 0x0 0x0 0x0 0x0 0x37 0xe9 0xff 0xed 0x0 0x0 0x0
|
||||||
|
0x2f 0x6 0x37 0x81 0x0 0xed 0x0 0x0 0x0 0x1 0x38 0x4c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x30 0x0 0x38 0xe9 0xff 0xf6 0x0 0x0 0x0 0x6 0x38 0x81 0x0 0xf6 0x0 0x0 0x0
|
||||||
|
0x31 0x0 0x39 0xeb 0xff 0xe4 0x0 0xfe 0xff 0x6 0x39 0x81 0x0 0xe4 0x0 0xfe 0xff
|
||||||
|
0x32 0x1 0x39 0x4d 0x0 0x0 0x0 0x0 0x0 0x0 0x3a 0xef 0xff 0xbd 0x0 0x0 0x0
|
||||||
|
0x33 0x6 0x3a 0x81 0x0 0xbd 0x0 0x0 0x0 0x1 0x3a 0x4e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x34 0x0 0x3c 0xed 0xff 0xcc 0x0 0x0 0x0 0x6 0x3c 0x81 0x0 0xcc 0x0 0x0 0x0
|
||||||
|
0x35 0x1 0x3d 0x4f 0x0 0x0 0x0 0x0 0x0 0x1 0x3e 0x50 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x36 0x0 0x3e 0x1 0x0 0xcd 0x0 0x0 0x0 0x6 0x3e 0x81 0x0 0xcd 0x0 0x0 0x0
|
||||||
|
0x37 0x0 0x3f 0x14 0x0 0x91 0x0 0x0 0x0 0x6 0x3f 0x81 0x0 0x91 0x0 0x0 0x0
|
||||||
|
0x38 0x1 0x3f 0x51 0x0 0x0 0x0 0x0 0x0 0x0 0x41 0x86 0x1 0x6e 0x0 0x0 0x0
|
||||||
|
0x39 0x6 0x41 0x81 0x0 0x6e 0x0 0x0 0x0 0x1 0x41 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3a 0x0 0x42 0x5e 0x1 0x55 0x0 0x0 0x0 0x6 0x42 0x81 0x0 0x55 0x0 0x0 0x0
|
||||||
|
0x3b 0x0 0x43 0x36 0x1 0x48 0x0 0x0 0x0 0x6 0x43 0x81 0x0 0x48 0x0 0x0 0x0
|
||||||
|
0x3c 0x0 0x44 0x31 0x1 0x36 0x0 0x0 0x0 0x6 0x44 0x81 0x0 0x36 0x0 0x0 0x0
|
||||||
|
0x3d 0x1 0x44 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x45 0x3d 0x1 0x2f 0x0 0x0 0x0
|
||||||
|
0x3e 0x6 0x45 0x81 0x0 0x2f 0x0 0x0 0x0 0x0 0x46 0x35 0x1 0x38 0x0 0x0 0x0
|
||||||
|
0x3f 0x6 0x46 0x81 0x0 0x38 0x0 0x0 0x0 0x1 0x46 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x40 0x0 0x47 0x76 0x1 0x37 0x0 0x0 0x0 0x6 0x47 0x81 0x0 0x37 0x0 0x0 0x0
|
||||||
|
0x41 0x0 0x48 0xbd 0x1 0x32 0x0 0x0 0x0 0x6 0x48 0x81 0x0 0x32 0x0 0x0 0x0
|
||||||
|
0x42 0x1 0x49 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x49 0xb0 0x1 0xd 0x0 0x0 0x0
|
||||||
|
0x43 0x6 0x49 0x81 0x0 0xd 0x0 0x0 0x0 0x0 0x4a 0x9b 0x1 0x1a 0x0 0x0 0x0
|
||||||
|
0x44 0x6 0x4a 0x81 0x0 0x1a 0x0 0x0 0x0 0x0 0x4b 0x7a 0x1 0x1c 0x0 0xfe 0xff
|
||||||
|
0x45 0x6 0x4b 0x81 0x0 0x1c 0x0 0xfe 0xff 0x0 0x4c 0x53 0x1 0x34 0x0 0x0 0x0
|
||||||
|
0x46 0x6 0x4c 0x81 0x0 0x34 0x0 0x0 0x0 0x1 0x4c 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x47 0x0 0x4d 0x24 0x1 0xfe 0xff 0x0 0x0 0x6 0x4d 0x81 0x0 0xfe 0xff 0x0 0x0
|
||||||
|
0x48 0x1 0x4e 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x4f 0x3c 0x1 0xff 0xff 0x0 0x0
|
||||||
|
0x49 0x6 0x4f 0x81 0x0 0xff 0xff 0x0 0x0 0x0 0x51 0x5 0x1 0x2a 0x0 0x0 0x0
|
||||||
|
0x4a 0x6 0x51 0x81 0x0 0x2a 0x0 0x0 0x0 0x1 0x52 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4b 0x0 0x53 0xd5 0x0 0x77 0x0 0x0 0x0 0x6 0x53 0x81 0x0 0x77 0x0 0x0 0x0
|
||||||
|
0x4c 0x0 0x54 0x86 0x0 0x89 0x0 0x0 0x0 0x6 0x54 0x81 0x0 0x89 0x0 0x0 0x0
|
||||||
|
0x4d 0x1 0x55 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x55 0x59 0x0 0xa3 0x0 0x0 0x0
|
||||||
|
0x4e 0x6 0x55 0x95 0x0 0xa3 0x0 0x0 0x0 0x0 0x56 0x3c 0x0 0xc2 0x0 0x0 0x0
|
||||||
|
0x4f 0x6 0x56 0x95 0x0 0xc2 0x0 0x0 0x0 0x1 0x56 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x50 0x0 0x57 0x23 0x0 0xe8 0x0 0x0 0x0 0x6 0x57 0x95 0x0 0xe8 0x0 0x0 0x0
|
||||||
|
0x51 0x1 0x57 0x50 0x0 0x0 0x0 0x0 0x0 0x0 0x58 0x11 0x0 0x5 0x1 0x0 0x0
|
||||||
|
0x52 0x6 0x58 0x95 0x0 0x5 0x1 0x0 0x0 0x0 0x59 0xfc 0xff 0xf 0x1 0x0 0x0
|
||||||
|
0x53 0x6 0x59 0x95 0x0 0xf 0x1 0x0 0x0 0x1 0x5a 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x54 0x0 0x5a 0xed 0xff 0x25 0x1 0x0 0x0 0x6 0x5a 0x95 0x0 0x25 0x1 0x0 0x0
|
||||||
|
0x55 0x0 0x5b 0xe7 0xff 0x32 0x1 0x0 0x0 0x6 0x5b 0x95 0x0 0x32 0x1 0x0 0x0
|
||||||
|
0x56 0x0 0x5c 0xb8 0xff 0xa5 0x1 0x0 0x0 0x6 0x5c 0x95 0x0 0xa5 0x1 0x0 0x0
|
||||||
|
0x57 0x0 0x5d 0xc0 0xff 0x7c 0x1 0x0 0x0 0x6 0x5d 0x95 0x0 0x7c 0x1 0x0 0x0
|
||||||
|
0x58 0x0 0x5e 0xde 0xff 0x3e 0x1 0x0 0x0 0x6 0x5e 0x82 0x0 0x3e 0x1 0x0 0x0
|
||||||
|
0x59 0x1 0x5f 0x52 0x0 0x0 0x0 0x0 0x0 0x0 0x5f 0xd8 0xff 0x46 0x1 0x0 0x0
|
||||||
|
0x5a 0x6 0x5f 0x82 0x0 0x46 0x1 0x0 0x0 0x1 0x60 0x53 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5b 0x0 0x60 0xd3 0xff 0x39 0x1 0x0 0x0 0x6 0x60 0x82 0x0 0x39 0x1 0x0 0x0
|
||||||
|
0x5c 0x0 0x61 0xc9 0xff 0x1f 0x1 0x0 0x0 0x6 0x61 0x82 0x0 0x1f 0x1 0x0 0x0
|
||||||
|
0x5d 0x1 0x61 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x63 0xbf 0xff 0xdd 0x0 0x0 0x0
|
||||||
|
0x5e 0x6 0x63 0x82 0x0 0xdd 0x0 0x0 0x0 0x1 0x63 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5f 0x1 0x66 0x57 0x0 0x0 0x0 0x0 0x0 0x0 0x6a 0xea 0xff 0xc6 0x0 0x0 0x0
|
||||||
|
0x60 0x6 0x6a 0x82 0x0 0xc6 0x0 0x0 0x0 0x1 0x6b 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x61 0x0 0x6c 0x59 0x0 0x9f 0x0 0x0 0x0 0x6 0x6c 0x96 0x0 0x9f 0x0 0x0 0x0
|
||||||
|
0x62 0x1 0x6d 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x6e 0x24 0x1 0x61 0x0 0x0 0x0
|
||||||
|
0x63 0x6 0x6e 0x96 0x0 0x61 0x0 0x0 0x0 0x1 0x6e 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x64 0x0 0x6f 0x39 0x1 0x24 0x0 0x0 0x0 0x6 0x6f 0x96 0x0 0x24 0x0 0x0 0x0
|
||||||
|
0x65 0x1 0x70 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x70 0x5b 0x1 0xfb 0xff 0x0 0x0
|
||||||
|
0x66 0x6 0x70 0x96 0x0 0xfb 0xff 0x0 0x0 0x0 0x71 0x7f 0x1 0xe0 0xff 0x0 0x0
|
||||||
|
0x67 0x6 0x71 0x96 0x0 0xe0 0xff 0x0 0x0 0x0 0x72 0xa3 0x1 0xd4 0xff 0x0 0x0
|
||||||
|
0x68 0x6 0x72 0x96 0x0 0xd4 0xff 0x0 0x0 0x1 0x72 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x69 0x0 0x73 0xc2 0x1 0xcf 0xff 0x0 0x0 0x6 0x73 0x96 0x0 0xcf 0xff 0x0 0x0
|
||||||
|
0x6a 0x0 0x74 0xd8 0x1 0xc7 0xff 0x0 0x0 0x6 0x74 0x96 0x0 0xc7 0xff 0x0 0x0
|
||||||
|
0x6b 0x1 0x74 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x75 0xe6 0x1 0xbe 0xff 0x0 0x0
|
||||||
|
0x6c 0x6 0x75 0x96 0x0 0xbe 0xff 0x0 0x0 0x0 0x76 0xeb 0x1 0xb2 0xff 0x0 0x0
|
||||||
|
0x6d 0x6 0x76 0x96 0x0 0xb2 0xff 0x0 0x0 0x1 0x77 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6e 0x0 0x77 0x8a 0x2 0x70 0xff 0x0 0x0 0x6 0x77 0x96 0x0 0x70 0xff 0x0 0x0
|
||||||
|
0x6f 0x0 0x78 0x92 0x2 0x9a 0xff 0x0 0x0 0x6 0x78 0x96 0x0 0x9a 0xff 0x0 0x0
|
||||||
|
0x70 0x1 0x78 0x57 0x0 0x0 0x0 0x0 0x0 0x0 0x79 0x7c 0x2 0xb9 0xff 0x0 0x0
|
||||||
|
0x71 0x6 0x79 0x96 0x0 0xb9 0xff 0x0 0x0 0x0 0x7a 0x59 0x2 0xb9 0xff 0x0 0x0
|
||||||
|
0x72 0x6 0x7a 0x83 0x0 0xb9 0xff 0x0 0x0 0x0 0x7b 0x33 0x2 0xa3 0xff 0x0 0x0
|
||||||
|
0x73 0x6 0x7b 0x83 0x0 0xa3 0xff 0x0 0x0 0x0 0x7c 0x27 0x2 0xac 0xff 0x0 0x0
|
||||||
|
0x74 0x6 0x7c 0x83 0x0 0xac 0xff 0x0 0x0 0x1 0x7d 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x75 0x0 0x7d 0x29 0x2 0xb1 0xff 0x0 0x0 0x6 0x7d 0x83 0x0 0xb1 0xff 0x0 0x0
|
||||||
|
0x76 0x0 0x7e 0x16 0x2 0xa9 0xff 0x2 0x0 0x6 0x7e 0x83 0x0 0xa9 0xff 0x2 0x0
|
||||||
|
0x77 0x1 0x7e 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x7f 0xd 0x2 0xaf 0xff 0x0 0x0
|
||||||
|
0x78 0x6 0x7f 0x83 0x0 0xaf 0xff 0x0 0x0 0x0 0x80 0x0 0x2 0xb5 0xff 0x0 0x0
|
||||||
|
0x79 0x6 0x80 0x70 0x0 0xb5 0xff 0x0 0x0 0x1 0x80 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7a 0x0 0x81 0x7 0x2 0xb7 0xff 0x0 0x0 0x6 0x81 0x70 0x0 0xb7 0xff 0x0 0x0
|
||||||
|
0x7b 0x0 0x82 0xa 0x2 0xc2 0xff 0x0 0x0 0x6 0x82 0x70 0x0 0xc2 0xff 0x0 0x0
|
||||||
|
0x7c 0x4 0x83 0x83 0x0 0x15 0x0 0x0 0x0 0x0 0x83 0x6 0x2 0xc6 0xff 0x0 0x0
|
||||||
|
0x7d 0x6 0x83 0x70 0x0 0xc6 0xff 0x0 0x0 0x0 0x84 0x0 0x2 0xc2 0xff 0x0 0x0
|
||||||
|
0x7e 0x6 0x84 0x70 0x0 0xc2 0xff 0x0 0x0 0x0 0x85 0x9 0x2 0xba 0xff 0x0 0x0
|
||||||
|
0x7f 0x6 0x85 0x70 0x0 0xba 0xff 0x0 0x0 0x1 0x85 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x80 0x0 0x86 0x8 0x2 0xb6 0xff 0x0 0x0 0x6 0x86 0x70 0x0 0xb6 0xff 0x0 0x0
|
||||||
|
0x81 0x0 0x87 0xfe 0x1 0xaf 0xff 0x0 0x0 0x6 0x87 0x70 0x0 0xaf 0xff 0x0 0x0
|
||||||
|
0x82 0x1 0x88 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x88 0xfc 0x1 0xae 0xff 0x0 0x0
|
||||||
|
0x83 0x6 0x88 0x70 0x0 0xae 0xff 0x0 0x0 0x0 0x89 0xf3 0x1 0xad 0xff 0x0 0x0
|
||||||
|
0x84 0x6 0x89 0x70 0x0 0xad 0xff 0x0 0x0 0x0 0x8a 0xe4 0x1 0xae 0xff 0x0 0x0
|
||||||
|
0x85 0x6 0x8a 0x70 0x0 0xae 0xff 0x0 0x0 0x1 0x8a 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x86 0x0 0x8b 0xd3 0x1 0xad 0xff 0x0 0x0 0x6 0x8b 0x70 0x0 0xad 0xff 0x0 0x0
|
||||||
|
0x87 0x0 0x8c 0xcd 0x1 0xb3 0xff 0x0 0x0 0x6 0x8c 0x70 0x0 0xb3 0xff 0x0 0x0
|
||||||
|
0x88 0x1 0x8d 0x57 0x0 0x0 0x0 0x0 0x0 0x0 0x8d 0xcf 0x1 0xae 0xff 0x0 0x0
|
||||||
|
0x89 0x6 0x8d 0x70 0x0 0xae 0xff 0x0 0x0 0x0 0x8e 0xdf 0x1 0xb0 0xff 0x0 0x0
|
||||||
|
0x8a 0x6 0x8e 0x70 0x0 0xb0 0xff 0x0 0x0 0x0 0x8f 0xec 0x1 0xb9 0xff 0x2 0x0
|
||||||
|
0x8b 0x6 0x8f 0x70 0x0 0xb9 0xff 0x2 0x0 0x0 0x90 0xfa 0x1 0xb5 0xff 0x0 0x0
|
||||||
|
0x8c 0x6 0x90 0x70 0x0 0xb5 0xff 0x0 0x0 0x1 0x90 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8d 0x0 0x91 0x1 0x2 0xcd 0xff 0x0 0x0 0x6 0x91 0x70 0x0 0xcd 0xff 0x0 0x0
|
||||||
|
0x8e 0x0 0x92 0xa 0x2 0xda 0xff 0x0 0x0 0x6 0x92 0x70 0x0 0xda 0xff 0x0 0x0
|
||||||
|
0x8f 0x0 0x93 0xe 0x2 0xd7 0xff 0x0 0x0 0x6 0x93 0x70 0x0 0xd7 0xff 0x0 0x0
|
||||||
|
0x90 0x1 0x94 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0x94 0x15 0x2 0xda 0xff 0x0 0x0
|
||||||
|
0x91 0x6 0x94 0x70 0x0 0xda 0xff 0x0 0x0 0x0 0x95 0x13 0x2 0xed 0xff 0x0 0x0
|
||||||
|
0x92 0x6 0x95 0x70 0x0 0xed 0xff 0x0 0x0 0x1 0x95 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x93 0x0 0x96 0xe1 0x1 0xf4 0xff 0x0 0x0 0x6 0x96 0x70 0x0 0xf4 0xff 0x0 0x0
|
||||||
|
0x94 0x1 0x96 0x5c 0x0 0x0 0x0 0x0 0x0 0x0 0x97 0x38 0x2 0x4 0x0 0x0 0x0
|
||||||
|
0x95 0x6 0x97 0x70 0x0 0x4 0x0 0x0 0x0 0x0 0x98 0x2f 0x2 0x13 0x0 0x0 0x0
|
||||||
|
0x96 0x6 0x98 0x5d 0x0 0x13 0x0 0x0 0x0 0x1 0x99 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x97 0x0 0x99 0x2a 0x2 0x23 0x0 0x0 0x0 0x6 0x99 0x5d 0x0 0x23 0x0 0x0 0x0
|
||||||
|
0x98 0x0 0x9a 0x28 0x2 0x25 0x0 0x0 0x0 0x6 0x9a 0x5d 0x0 0x25 0x0 0x0 0x0
|
||||||
|
0x99 0x1 0x9a 0x5e 0x0 0x0 0x0 0x0 0x0 0x0 0x9b 0x22 0x2 0x2c 0x0 0x0 0x0
|
||||||
|
0x9a 0x6 0x9b 0x5d 0x0 0x2c 0x0 0x0 0x0 0x1 0x9b 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9b 0x0 0x9c 0x18 0x2 0x34 0x0 0x0 0x0 0x6 0x9c 0x5d 0x0 0x34 0x0 0x0 0x0
|
||||||
|
0x9c 0x0 0x9d 0xe3 0x1 0x38 0x0 0x0 0x0 0x6 0x9d 0x5d 0x0 0x38 0x0 0x0 0x0
|
||||||
|
0x9d 0x1 0x9e 0x60 0x0 0x0 0x0 0x0 0x0 0x0 0x9e 0x2f 0x2 0x50 0x0 0x0 0x0
|
||||||
|
0x9e 0x6 0x9e 0x5d 0x0 0x50 0x0 0x0 0x0 0x1 0x9f 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9f 0x0 0x9f 0x23 0x2 0x5a 0x0 0x0 0x0 0x6 0x9f 0x5d 0x0 0x5a 0x0 0x0 0x0
|
||||||
|
0xa0 0x0 0xa0 0x1d 0x2 0x6c 0x0 0x0 0x0 0x6 0xa0 0x5d 0x0 0x6c 0x0 0x0 0x0
|
||||||
|
0xa1 0x1 0xa0 0x60 0x0 0x0 0x0 0x0 0x0 0x0 0xa1 0x15 0x2 0x72 0x0 0x0 0x0
|
||||||
|
0xa2 0x6 0xa1 0x5d 0x0 0x72 0x0 0x0 0x0 0x0 0xa2 0xe 0x2 0x7f 0x0 0x0 0x0
|
||||||
|
0xa3 0x6 0xa2 0x5d 0x0 0x7f 0x0 0x0 0x0 0x0 0xa3 0x6 0x2 0x88 0x0 0x0 0x0
|
||||||
|
0xa4 0x6 0xa3 0x5d 0x0 0x88 0x0 0x0 0x0 0x1 0xa4 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa5 0x0 0xa4 0xfd 0x1 0x96 0x0 0x0 0x0 0x6 0xa4 0x5d 0x0 0x96 0x0 0x0 0x0
|
||||||
|
0xa6 0x0 0xa5 0xc2 0x1 0x91 0x0 0x0 0x0 0x6 0xa5 0x5d 0x0 0x91 0x0 0x0 0x0
|
||||||
|
0xa7 0x0 0xa6 0x0 0x2 0xaf 0x0 0x0 0x0 0x6 0xa6 0x5d 0x0 0xaf 0x0 0x0 0x0
|
||||||
|
0xa8 0x0 0xa7 0xe4 0x1 0xb2 0x0 0x0 0x0 0x6 0xa7 0x5d 0x0 0xb2 0x0 0x0 0x0
|
||||||
|
0xa9 0x1 0xa7 0x62 0x0 0x0 0x0 0x0 0x0 0x0 0xa8 0xc9 0x1 0xb3 0x0 0x0 0x0
|
||||||
|
0xaa 0x6 0xa8 0x5d 0x0 0xb3 0x0 0x0 0x0 0x1 0xa9 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xab 0x0 0xa9 0xaf 0x1 0xb6 0x0 0x2 0x0 0x6 0xa9 0x5d 0x0 0xb6 0x0 0x2 0x0
|
||||||
|
0xac 0x0 0xaa 0xa2 0x1 0xbc 0x0 0x0 0x0 0x6 0xaa 0x5d 0x0 0xbc 0x0 0x0 0x0
|
||||||
|
0xad 0x0 0xab 0x69 0x1 0xae 0x0 0x0 0x0 0x6 0xab 0x5d 0x0 0xae 0x0 0x0 0x0
|
||||||
|
0xae 0x0 0xac 0x93 0x1 0xcf 0x0 0x0 0x0 0x6 0xac 0x5d 0x0 0xcf 0x0 0x0 0x0
|
||||||
|
0xaf 0x1 0xac 0x62 0x0 0x0 0x0 0x0 0x0 0x0 0xad 0x4c 0x1 0xb8 0x0 0x0 0x0
|
||||||
|
0xb0 0x6 0xad 0x5d 0x0 0xb8 0x0 0x0 0x0 0x1 0xad 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb1 0x0 0xae 0x43 0x1 0xc0 0x0 0x0 0x0 0x6 0xae 0x5d 0x0 0xc0 0x0 0x0 0x0
|
||||||
|
0xb2 0x0 0xaf 0x60 0x1 0xdd 0x0 0x0 0x0 0x6 0xaf 0x5d 0x0 0xdd 0x0 0x0 0x0
|
||||||
|
0xb3 0x0 0xb0 0x48 0x1 0xd5 0x0 0x0 0x0 0x6 0xb0 0x5d 0x0 0xd5 0x0 0x0 0x0
|
||||||
|
0xb4 0x0 0xb1 0x3f 0x1 0xe0 0x0 0x0 0x0 0x6 0xb1 0x5d 0x0 0xe0 0x0 0x0 0x0
|
||||||
|
0xb5 0x0 0xb2 0x1a 0x1 0xd4 0x0 0x0 0x0 0x6 0xb2 0x5d 0x0 0xd4 0x0 0x0 0x0
|
||||||
|
0xb6 0x1 0xb2 0x61 0x0 0x0 0x0 0x0 0x0 0x0 0xb3 0x26 0x1 0xe7 0x0 0x0 0x0
|
||||||
|
0xb7 0x6 0xb3 0x5d 0x0 0xe7 0x0 0x0 0x0 0x0 0xb4 0x47 0x1 0x4 0x1 0x0 0x0
|
||||||
|
0xb8 0x6 0xb4 0x5d 0x0 0x4 0x1 0x0 0x0 0x0 0xb5 0x3c 0x1 0xff 0x0 0x0 0x0
|
||||||
|
0xb9 0x6 0xb5 0x5d 0x0 0xff 0x0 0x0 0x0 0x1 0xb6 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xba 0x0 0xb6 0x2f 0x1 0xf8 0x0 0x0 0x0 0x6 0xb6 0x5d 0x0 0xf8 0x0 0x0 0x0
|
||||||
|
0xbb 0x0 0xb7 0x32 0x1 0xf9 0x0 0x0 0x0 0x6 0xb7 0x5d 0x0 0xf9 0x0 0x0 0x0
|
||||||
|
0xbc 0x5 0xb7 0xb7 0x0 0xf9 0x0 0x0 0x0 0x1 0xb7 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xbd 0x0 0xb8 0x32 0x1 0xf2 0x0 0x0 0x0 0x6 0xb8 0x5d 0x0 0xf2 0x0 0x0 0x0
|
||||||
|
0xbe 0x0 0xb9 0x25 0x1 0xee 0x0 0x0 0x0 0x6 0xb9 0x5d 0x0 0xee 0x0 0x0 0x0
|
||||||
|
0xbf 0x0 0xba 0x14 0x1 0xe3 0x0 0x0 0x0 0x6 0xba 0x5d 0x0 0xe3 0x0 0x0 0x0
|
||||||
|
0xc0 0x1 0xbb 0x60 0x0 0x0 0x0 0x0 0x0 0x0 0xbb 0x0 0x1 0xd3 0x0 0x0 0x0
|
||||||
|
0xc1 0x6 0xbb 0x5d 0x0 0xd3 0x0 0x0 0x0 0x0 0xbc 0xe4 0x0 0xbe 0x0 0x0 0x0
|
||||||
|
0xc2 0x6 0xbc 0x5d 0x0 0xbe 0x0 0x0 0x0 0x1 0xbc 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc3 0x0 0xbd 0xc7 0x0 0xaa 0x0 0x0 0x0 0x6 0xbd 0x5d 0x0 0xaa 0x0 0x0 0x0
|
||||||
|
0xc4 0x1 0xbd 0x62 0x0 0x0 0x0 0x0 0x0 0x0 0xbe 0xa0 0x0 0x8c 0x0 0x0 0x0
|
||||||
|
0xc5 0x6 0xbe 0x5d 0x0 0x8c 0x0 0x0 0x0 0x0 0xbf 0xbc 0x0 0xa3 0x0 0x0 0x0
|
||||||
|
0xc6 0x6 0xbf 0x5d 0x0 0xa3 0x0 0x0 0x0 0x1 0xc0 0x63 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc7 0x0 0xc0 0xbf 0x0 0xa4 0x0 0x0 0x0 0x6 0xc0 0x5d 0x0 0xa4 0x0 0x0 0x0
|
||||||
|
0xc8 0x0 0xc1 0xbe 0x0 0x9f 0x0 0x0 0x0 0x6 0xc1 0x5d 0x0 0x9f 0x0 0x0 0x0
|
||||||
|
0xc9 0x0 0xc2 0xb4 0x0 0x93 0x0 0x0 0x0 0x6 0xc2 0x5d 0x0 0x93 0x0 0x0 0x0
|
||||||
|
0xca 0x1 0xc2 0x5c 0x0 0x0 0x0 0x0 0x0 0x0 0xc3 0xc6 0x0 0xa1 0x0 0x0 0x0
|
||||||
|
0xcb 0x6 0xc3 0x5d 0x0 0xa1 0x0 0x0 0x0 0x0 0xc4 0xd0 0x0 0xa6 0x0 0x0 0x0
|
||||||
|
0xcc 0x6 0xc4 0x5d 0x0 0xa6 0x0 0x0 0x0 0x1 0xc4 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xcd 0x0 0xc5 0xe8 0x0 0xb9 0x0 0x0 0x0 0x6 0xc5 0x5d 0x0 0xb9 0x0 0x0 0x0
|
||||||
|
0xce 0x1 0xc6 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0xc6 0xe7 0x0 0xb7 0x0 0x0 0x0
|
||||||
|
0xcf 0x6 0xc6 0x5d 0x0 0xb7 0x0 0x0 0x0 0x1 0xc7 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd0 0x0 0xc7 0xe9 0x0 0xba 0x0 0x0 0x0 0x6 0xc7 0x5d 0x0 0xba 0x0 0x0 0x0
|
||||||
|
0xd1 0x0 0xc8 0xf5 0x0 0xc6 0x0 0x0 0x0 0x6 0xc8 0x5d 0x0 0xc6 0x0 0x0 0x0
|
||||||
|
0xd2 0x0 0xc9 0x2 0x1 0xcf 0x0 0x0 0x0 0x6 0xc9 0x5d 0x0 0xcf 0x0 0x0 0x0
|
||||||
|
0xd3 0x1 0xc9 0x5e 0x0 0x0 0x0 0x0 0x0 0x0 0xca 0x13 0x1 0xdd 0x0 0x0 0x0
|
||||||
|
0xd4 0x6 0xca 0x5d 0x0 0xdd 0x0 0x0 0x0 0x1 0xcb 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd5 0x0 0xcb 0x18 0x1 0xdf 0x0 0x0 0x0 0x6 0xcb 0x5d 0x0 0xdf 0x0 0x0 0x0
|
||||||
|
0xd6 0x1 0xcc 0x56 0x0 0x0 0x0 0x0 0x0 0x0 0xcc 0x27 0x1 0xea 0x0 0x0 0x0
|
||||||
|
0xd7 0x6 0xcc 0x5d 0x0 0xea 0x0 0x0 0x0 0x0 0xcd 0x2a 0x1 0xed 0x0 0x0 0x0
|
||||||
|
0xd8 0x6 0xcd 0x5d 0x0 0xed 0x0 0x0 0x0 0x0 0xce 0x35 0x1 0xf3 0x0 0x0 0x0
|
||||||
|
0xd9 0x6 0xce 0x5d 0x0 0xf3 0x0 0x0 0x0 0x1 0xce 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xda 0x0 0xcf 0x44 0x1 0xfe 0x0 0x0 0x0 0x6 0xcf 0x5d 0x0 0xfe 0x0 0x0 0x0
|
||||||
|
0xdb 0x1 0xcf 0x44 0x0 0x0 0x0 0x0 0x0 0x0 0xd0 0x4f 0x1 0x9 0x1 0x0 0x0
|
||||||
|
0xdc 0x6 0xd0 0x5d 0x0 0x9 0x1 0x0 0x0 0x1 0xd1 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xdd 0x0 0xd1 0x37 0x1 0xf2 0x0 0x0 0x0 0x6 0xd1 0x5d 0x0 0xf2 0x0 0x0 0x0
|
||||||
|
0xde 0x0 0xd2 0x71 0x1 0x1e 0x1 0x0 0x0 0x6 0xd2 0x5d 0x0 0x1e 0x1 0x0 0x0
|
||||||
|
0xdf 0x0 0xd3 0x42 0x1 0xf8 0x0 0xfe 0xff 0x6 0xd3 0x5d 0x0 0xf8 0x0 0xfe 0xff
|
||||||
|
0xe0 0x1 0xd3 0x49 0x0 0x0 0x0 0x0 0x0 0x0 0xd4 0x59 0x1 0x8 0x1 0x0 0x0
|
||||||
|
0xe1 0x6 0xd4 0x5d 0x0 0x8 0x1 0x0 0x0 0x1 0xd4 0x48 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe2 0x0 0xd5 0x75 0x1 0x22 0x1 0x0 0x0 0x6 0xd5 0x5d 0x0 0x22 0x1 0x0 0x0
|
||||||
|
0xe3 0x1 0xd5 0x47 0x0 0x0 0x0 0x0 0x0 0x0 0xd6 0x64 0x1 0x10 0x1 0x0 0x0
|
||||||
|
0xe4 0x6 0xd6 0x5d 0x0 0x10 0x1 0x0 0x0 0x0 0xd7 0x38 0x1 0xec 0x0 0xff 0xff
|
||||||
|
0xe5 0x6 0xd7 0x5d 0x0 0xec 0x0 0xff 0xff 0x1 0xd8 0x48 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe6 0x0 0xd8 0x66 0x1 0x14 0x1 0xff 0xff 0x6 0xd8 0x5d 0x0 0x14 0x1 0xff 0xff
|
||||||
|
0xe7 0x0 0xd9 0x58 0x1 0xc 0x1 0x0 0x0 0x6 0xd9 0x5d 0x0 0xc 0x1 0x0 0x0
|
||||||
|
0xe8 0x1 0xd9 0x49 0x0 0x0 0x0 0x0 0x0 0x0 0xda 0x3b 0x1 0xf6 0x0 0x0 0x0
|
||||||
|
0xe9 0x6 0xda 0x5d 0x0 0xf6 0x0 0x0 0x0 0x0 0xdb 0x53 0x1 0xa 0x1 0x0 0x0
|
||||||
|
0xea 0x6 0xdb 0x5d 0x0 0xa 0x1 0x0 0x0 0x0 0xdc 0x38 0x1 0xf5 0x0 0x0 0x0
|
||||||
|
0xeb 0x6 0xdc 0x5d 0x0 0xf5 0x0 0x0 0x0 0x4 0xdd 0x5a 0x0 0x15 0x0 0x0 0x0
|
||||||
|
0xec 0x1 0xdd 0x4a 0x0 0x0 0x0 0x0 0x0 0x0 0xdd 0x7 0x1 0xd5 0x0 0x0 0x0
|
||||||
|
0xed 0x6 0xdd 0x5d 0x0 0xd5 0x0 0x0 0x0 0x0 0xde 0x11 0x1 0xdb 0x0 0xfe 0xff
|
||||||
|
0xee 0x6 0xde 0x5d 0x0 0xdb 0x0 0xfe 0xff 0x1 0xde 0x4b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xef 0x0 0xdf 0x7 0x1 0xd1 0x0 0x0 0x0 0x6 0xdf 0x5d 0x0 0xd1 0x0 0x0 0x0
|
||||||
|
0xf0 0x1 0xdf 0x4c 0x0 0x0 0x0 0x0 0x0 0x0 0xe0 0xc 0x1 0xd4 0x0 0x0 0x0
|
||||||
|
0xf1 0x6 0xe0 0x5d 0x0 0xd4 0x0 0x0 0x0 0x0 0xe1 0xd6 0x0 0xa9 0x0 0x0 0x0
|
||||||
|
0xf2 0x6 0xe1 0x5d 0x0 0xa9 0x0 0x0 0x0 0x1 0xe2 0x4d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf3 0x0 0xe2 0xdb 0x0 0xac 0x0 0x0 0x0 0x6 0xe2 0x5d 0x0 0xac 0x0 0x0 0x0
|
||||||
|
0xf4 0x0 0xe4 0x2d 0x1 0xad 0x0 0x0 0x0 0x6 0xe4 0x5d 0x0 0xad 0x0 0x0 0x0
|
||||||
|
0xf5 0x1 0xe4 0x4e 0x0 0x0 0x0 0x0 0x0 0x0 0xe6 0xf3 0x0 0x8b 0x0 0x0 0x0
|
||||||
|
0xf6 0x6 0xe6 0x5d 0x0 0x8b 0x0 0x0 0x0 0x1 0xe6 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf7 0x1 0xe8 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0xeb 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf8 0x1 0xee 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0xf0 0xf7 0x0 0x87 0x0 0x0 0x0
|
||||||
|
0xf9 0x6 0xf0 0x74 0x0 0x87 0x0 0x0 0x0 0x1 0xf0 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfa 0x0 0xf2 0xd8 0x0 0x7f 0x0 0x0 0x0 0x6 0xf2 0x8c 0x0 0x7f 0x0 0x0 0x0
|
||||||
|
0xfb 0x1 0xf2 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0xf4 0xcb 0x0 0x7c 0x0 0x0 0x0
|
||||||
|
0xfc 0x6 0xf4 0x8c 0x0 0x7c 0x0 0x0 0x0 0x1 0xf5 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfd 0x0 0xf6 0x1c 0x1 0x75 0x0 0x0 0x0 0x6 0xf6 0xa1 0x0 0x75 0x0 0x0 0x0
|
||||||
|
0xfe 0x1 0xf6 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0xf7 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xff 0x0 0xf8 0x67 0x1 0x3a 0x0 0x2 0x0 0x6 0xf8 0xa1 0x0 0x3a 0x0 0x2 0x0
|
||||||
|
0x0 0x0 0xf9 0x24 0x1 0x2 0x0 0x0 0x0 0x6 0xf9 0xa1 0x0 0x2 0x0 0x0 0x0
|
||||||
|
0x1 0x1 0xfa 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xfa 0x19 0x1 0xd6 0xff 0x0 0x0
|
||||||
|
0x2 0x6 0xfa 0xa1 0x0 0xd6 0xff 0x0 0x0 0x0 0xfb 0x1e 0x1 0xb9 0xff 0x0 0x0
|
||||||
|
0x3 0x6 0xfb 0xa1 0x0 0xb9 0xff 0x0 0x0 0x0 0xfc 0x22 0x1 0xa6 0xff 0x0 0x0
|
||||||
|
0x4 0x6 0xfc 0xa1 0x0 0xa6 0xff 0x0 0x0 0x1 0xfc 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5 0x0 0xfd 0x68 0x1 0x47 0xff 0x0 0x0 0x6 0xfd 0xa1 0x0 0x47 0xff 0x0 0x0
|
||||||
|
0x6 0x0 0xfe 0x3e 0x1 0x58 0xff 0x0 0x0 0x6 0xfe 0xa1 0x0 0x58 0xff 0x0 0x0
|
||||||
|
0x7 0x0 0xff 0x32 0x1 0x5f 0xff 0x0 0x0 0x6 0xff 0xa1 0x0 0x5f 0xff 0x0 0x0
|
||||||
|
0x8 0x0 0x0 0x19 0x1 0x67 0xff 0x0 0x0 0x6 0x0 0xa1 0x0 0x67 0xff 0x0 0x0
|
||||||
|
0x9 0x0 0x1 0xff 0x0 0x7f 0xff 0x0 0x0 0x6 0x1 0xa1 0x0 0x7f 0xff 0x0 0x0
|
||||||
|
0xa 0x1 0x1 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0x2 0xf5 0x0 0x92 0xff 0x0 0x0
|
||||||
|
0xb 0x6 0x2 0xa1 0x0 0x92 0xff 0x0 0x0 0x1 0x3 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc 0x0 0x4 0xe1 0x0 0x9f 0xff 0xfe 0xff 0x6 0x4 0xa1 0x0 0x9f 0xff 0xfe 0xff
|
||||||
|
0xd 0x1 0x5 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0xb 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe 0x0 0xc 0xa3 0x0 0x91 0xff 0x0 0x0 0x6 0xc 0xb8 0x0 0x91 0xff 0x0 0x0
|
||||||
|
0xf 0x1 0xd 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0xe 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x10 0x1 0x10 0x61 0x0 0x0 0x0 0x0 0x0 0x1 0x13 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x11 0x1 0x14 0x6d 0x0 0x0 0x0 0x0 0x0 0x1 0x17 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x12 0x1 0x18 0x65 0x0 0x0 0x0 0x0 0x0 0x1 0x19 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x13 0x0 0x1b 0xe5 0x0 0xa0 0xff 0x0 0x0 0x6 0x1b 0x54 0x1 0xa0 0xff 0x0 0x0
|
||||||
|
0x14 0x1 0x1c 0x6c 0x0 0x0 0x0 0x0 0x0 0x0 0x1d 0x12 0x1 0xa6 0xff 0x0 0x0
|
||||||
|
0x15 0x6 0x1d 0x54 0x1 0xa6 0xff 0x0 0x0 0x1 0x1d 0x6d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x16 0x0 0x1e 0x10 0x1 0xaa 0xff 0x0 0x0 0x6 0x1e 0x6b 0x1 0xaa 0xff 0x0 0x0
|
||||||
|
0x17 0x1 0x1e 0x69 0x0 0x0 0x0 0x0 0x0 0x0 0x1f 0x23 0x1 0xb2 0xff 0x0 0x0
|
||||||
|
0x18 0x6 0x1f 0x6b 0x1 0xb2 0xff 0x0 0x0 0x0 0x20 0x46 0x1 0xac 0xff 0x0 0x0
|
||||||
|
0x19 0x6 0x20 0x6b 0x1 0xac 0xff 0x0 0x0 0x1 0x21 0x6b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1a 0x0 0x21 0x66 0x1 0xa7 0xff 0x0 0x0 0x6 0x21 0x4c 0x1 0xa7 0xff 0x0 0x0
|
||||||
|
0x1b 0x1 0x22 0x6e 0x0 0x0 0x0 0x0 0x0 0x0 0x22 0x8f 0x1 0x9f 0xff 0x0 0x0
|
||||||
|
0x1c 0x6 0x22 0x36 0x1 0x9f 0xff 0x0 0x0 0x0 0x23 0xdf 0x1 0x8b 0xff 0x0 0x0
|
||||||
|
0x1d 0x6 0x23 0x36 0x1 0x8b 0xff 0x0 0x0 0x1 0x23 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1e 0x0 0x24 0x92 0x1 0x9d 0xff 0xff 0xff 0x6 0x24 0x19 0x1 0x9d 0xff 0xff 0xff
|
||||||
|
0x1f 0x0 0x25 0x82 0x1 0xa1 0xff 0x0 0x0 0x6 0x25 0x2 0x1 0xa1 0xff 0x0 0x0
|
||||||
|
0x20 0x1 0x25 0x6a 0x0 0x0 0x0 0x0 0x0 0x0 0x26 0x2a 0x1 0xb7 0xff 0x0 0x0
|
||||||
|
0x21 0x6 0x26 0xef 0x0 0xb7 0xff 0x0 0x0 0x1 0x27 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x22 0x0 0x27 0x6 0x1 0xbf 0xff 0x0 0x0 0x6 0x27 0xef 0x0 0xbf 0xff 0x0 0x0
|
||||||
|
0x23 0x1 0x28 0x6e 0x0 0x0 0x0 0x0 0x0 0x0 0x29 0x1b 0x1 0xb9 0xff 0x0 0x0
|
||||||
|
0x24 0x6 0x29 0xd8 0x0 0xb9 0xff 0x0 0x0 0x1 0x2a 0x74 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x25 0x1 0x2b 0x70 0x0 0x0 0x0 0x0 0x0 0x0 0x2c 0xf9 0x0 0xbc 0xff 0x0 0x0
|
||||||
|
0x26 0x6 0x2c 0xd8 0x0 0xbc 0xff 0x0 0x0 0x1 0x2d 0x72 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x27 0x1 0x2f 0x6b 0x0 0x0 0x0 0x0 0x0 0x0 0x30 0xa5 0x0 0x86 0xff 0x0 0x0
|
||||||
|
0x28 0x6 0x30 0xeb 0x0 0x86 0xff 0x0 0x0 0x1 0x30 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x29 0x1 0x32 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x34 0x5c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2a 0x1 0x35 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0x36 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2b 0x0 0x38 0x78 0x0 0x7b 0xff 0x0 0x0 0x6 0x38 0x30 0x1 0x7b 0xff 0x0 0x0
|
||||||
|
0x2c 0x1 0x39 0x4d 0x0 0x0 0x0 0x0 0x0 0x1 0x3a 0x4c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2d 0x1 0x3b 0x45 0x0 0x0 0x0 0x0 0x0 0x1 0x3e 0x47 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2e 0x0 0x3f 0xbe 0x0 0xbb 0xff 0x0 0x0 0x6 0x3f 0x64 0x1 0xbb 0xff 0x0 0x0
|
||||||
|
0x2f 0x1 0x3f 0x46 0x0 0x0 0x0 0x0 0x0 0x1 0x40 0x45 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x30 0x0 0x41 0xd4 0x0 0xc4 0xff 0x0 0x0 0x6 0x41 0x81 0x1 0xc4 0xff 0x0 0x0
|
||||||
|
0x31 0x1 0x43 0x44 0x0 0x0 0x0 0x0 0x0 0x0 0x43 0x37 0x1 0xb0 0xff 0x0 0x0
|
||||||
|
0x32 0x6 0x43 0x97 0x1 0xb0 0xff 0x0 0x0 0x1 0x44 0x46 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x33 0x0 0x44 0x39 0x1 0xab 0xff 0x0 0x0 0x6 0x44 0x97 0x1 0xab 0xff 0x0 0x0
|
||||||
|
0x34 0x0 0x45 0x53 0x1 0x9f 0xff 0x0 0x0 0x6 0x45 0x97 0x1 0x9f 0xff 0x0 0x0
|
||||||
|
0x35 0x1 0x45 0x48 0x0 0x0 0x0 0x0 0x0 0x0 0x46 0x74 0x1 0x89 0xff 0x0 0x0
|
||||||
|
0x36 0x6 0x46 0x7b 0x1 0x89 0xff 0x0 0x0 0x0 0x47 0x6c 0x1 0x90 0xff 0x0 0x0
|
||||||
|
0x37 0x6 0x47 0x5c 0x1 0x90 0xff 0x0 0x0 0x1 0x48 0x47 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x38 0x0 0x48 0x4e 0x1 0x99 0xff 0x0 0x0 0x6 0x48 0x3f 0x1 0x99 0xff 0x0 0x0
|
||||||
|
0x39 0x0 0x49 0x6d 0x1 0x95 0xff 0x0 0x0 0x6 0x49 0x25 0x1 0x95 0xff 0x0 0x0
|
||||||
|
0x3a 0x1 0x4a 0x48 0x0 0x0 0x0 0x0 0x0 0x1 0x4c 0x49 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3b 0x1 0x4e 0x4a 0x0 0x0 0x0 0x0 0x0 0x0 0x4e 0x4a 0x6 0xc3 0xfd 0x0 0x0
|
||||||
|
0x3c 0x6 0x4e 0xdf 0x0 0xc3 0xfd 0x0 0x0 0x1 0x4f 0x4b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3d 0x0 0x4f 0x62 0x4 0x58 0xfe 0x0 0x0 0x6 0x4f 0xdf 0x0 0x58 0xfe 0x0 0x0
|
||||||
|
0x3e 0x0 0x50 0x44 0x3 0xaa 0xfe 0x0 0x0 0x6 0x50 0xdf 0x0 0xaa 0xfe 0x0 0x0
|
||||||
|
0x3f 0x0 0x51 0x95 0x2 0xe2 0xfe 0x0 0x0 0x6 0x51 0xc1 0x0 0xe2 0xfe 0x0 0x0
|
||||||
|
0x40 0x1 0x51 0x4c 0x0 0x0 0x0 0x0 0x0 0x0 0x52 0x24 0x2 0x8 0xff 0x0 0x0
|
||||||
|
0x41 0x6 0x52 0xc1 0x0 0x8 0xff 0x0 0x0 0x1 0x52 0x4d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x42 0x0 0x53 0xcd 0x1 0x2c 0xff 0x0 0x0 0x6 0x53 0xa4 0x0 0x2c 0xff 0x0 0x0
|
||||||
|
0x43 0x0 0x54 0x96 0x1 0x4b 0xff 0x0 0x0 0x6 0x54 0xa4 0x0 0x4b 0xff 0x0 0x0
|
||||||
|
0x44 0x0 0x55 0x66 0x1 0x5d 0xff 0x0 0x0 0x6 0x55 0xa4 0x0 0x5d 0xff 0x0 0x0
|
||||||
|
0x45 0x0 0x56 0x44 0x1 0x6e 0xff 0x0 0x0 0x6 0x56 0xa4 0x0 0x6e 0xff 0x0 0x0
|
||||||
|
0x46 0x0 0x57 0x1c 0x1 0x7b 0xff 0x1 0x0 0x6 0x57 0x90 0x0 0x7b 0xff 0x1 0x0
|
||||||
|
0x47 0x1 0x57 0x4e 0x0 0x0 0x0 0x0 0x0 0x0 0x58 0xfc 0x0 0x8a 0xff 0x0 0x0
|
||||||
|
0x48 0x6 0x58 0x90 0x0 0x8a 0xff 0x0 0x0 0x1 0x59 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x49 0x0 0x59 0xe2 0x0 0x97 0xff 0x0 0x0 0x6 0x59 0x90 0x0 0x97 0xff 0x0 0x0
|
||||||
|
0x4a 0x0 0x5a 0xd8 0x0 0x9d 0xff 0x0 0x0 0x6 0x5a 0x90 0x0 0x9d 0xff 0x0 0x0
|
||||||
|
0x4b 0x0 0x5b 0xc6 0x0 0xa5 0xff 0x0 0x0 0x6 0x5b 0x90 0x0 0xa5 0xff 0x0 0x0
|
||||||
|
0x4c 0x1 0x5b 0x50 0x0 0x0 0x0 0x0 0x0 0x1 0x5c 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4d 0x0 0x5d 0xef 0x0 0x92 0xff 0x0 0x0 0x6 0x5d 0x90 0x0 0x92 0xff 0x0 0x0
|
||||||
|
0x4e 0x1 0x5d 0x50 0x0 0x0 0x0 0x0 0x0 0x1 0x60 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4f 0x0 0x61 0xdb 0x0 0x9d 0xff 0x0 0x0 0x6 0x61 0x90 0x0 0x9d 0xff 0x0 0x0
|
||||||
|
0x50 0x1 0x61 0x4e 0x0 0x0 0x0 0x0 0x0 0x1 0x62 0x48 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x51 0x1 0x65 0x41 0x0 0x0 0x0 0x0 0x0 0x1 0x66 0x43 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x52 0x1 0x67 0x44 0x0 0x0 0x0 0x0 0x0 0x1 0x6a 0x4b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x53 0x1 0x6b 0x4c 0x0 0x0 0x0 0x0 0x0 0x1 0x6c 0x47 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x54 0x1 0x6e 0x4e 0x0 0x0 0x0 0x0 0x0 0x1 0x70 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x55 0x1 0x71 0x52 0x0 0x0 0x0 0x0 0x0 0x0 0x72 0xc5 0x0 0x99 0xff 0x1 0x0
|
||||||
|
0x56 0x6 0x72 0x13 0x1 0x99 0xff 0x1 0x0 0x0 0x74 0xec 0x0 0xc2 0xff 0x1 0x0
|
||||||
|
0x57 0x6 0x74 0x2f 0x1 0xc2 0xff 0x1 0x0 0x1 0x74 0x50 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x58 0x1 0x76 0x52 0x0 0x0 0x0 0x0 0x0 0x0 0x76 0x2d 0x1 0x2f 0x0 0x0 0x0
|
||||||
|
0x59 0x6 0x76 0x44 0x1 0x2f 0x0 0x0 0x0 0x0 0x77 0xeb 0x0 0x65 0x0 0x0 0x0
|
||||||
|
0x5a 0x6 0x77 0x44 0x1 0x65 0x0 0x0 0x0 0x0 0x78 0xe9 0x0 0x67 0x0 0x0 0x0
|
||||||
|
0x5b 0x6 0x78 0x44 0x1 0x67 0x0 0x0 0x0 0x1 0x78 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5c 0x0 0x79 0xdb 0x0 0xae 0x0 0x0 0x0 0x6 0x79 0x44 0x1 0xae 0x0 0x0 0x0
|
||||||
|
0x5d 0x1 0x79 0x50 0x0 0x0 0x0 0x0 0x0 0x0 0x7a 0xe5 0x0 0xf4 0x0 0x2 0x0
|
||||||
|
0x5e 0x6 0x7a 0x26 0x1 0xf4 0x0 0x2 0x0 0x0 0x7b 0xe3 0x0 0xfc 0x0 0x0 0x0
|
||||||
|
0x5f 0x6 0x7b 0x13 0x1 0xfc 0x0 0x0 0x0 0x0 0x7c 0xc2 0x0 0xd 0x1 0x0 0x0
|
||||||
|
0x60 0x6 0x7c 0xff 0x0 0xd 0x1 0x0 0x0 0x0 0x7d 0xc2 0x0 0x4c 0x1 0x0 0x0
|
||||||
|
0x61 0x6 0x7d 0xff 0x0 0x4c 0x1 0x0 0x0 0x1 0x7d 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x62 0x0 0x7e 0x96 0x0 0x43 0x1 0x0 0x0 0x6 0x7e 0xe7 0x0 0x43 0x1 0x0 0x0
|
||||||
|
0x63 0x1 0x7e 0x52 0x0 0x0 0x0 0x0 0x0 0x0 0x7f 0x48 0x0 0x5d 0x1 0x0 0x0
|
||||||
|
0x64 0x6 0x7f 0xd4 0x0 0x5d 0x1 0x0 0x0 0x1 0x7f 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x65 0x0 0x80 0xe8 0xff 0x63 0x1 0x0 0x0 0x6 0x80 0xd4 0x0 0x63 0x1 0x0 0x0
|
||||||
|
0x66 0x0 0x81 0x9a 0xff 0x7c 0x1 0x0 0x0 0x6 0x81 0xb5 0x0 0x7c 0x1 0x0 0x0
|
||||||
|
0x67 0x1 0x82 0x56 0x0 0x0 0x0 0x0 0x0 0x0 0x82 0x69 0xff 0x60 0x1 0x0 0x0
|
||||||
|
0x68 0x6 0x82 0xb5 0x0 0x60 0x1 0x0 0x0 0x0 0x83 0x67 0xff 0x2b 0x1 0x0 0x0
|
||||||
|
0x69 0x6 0x83 0xb5 0x0 0x2b 0x1 0x0 0x0 0x1 0x83 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6a 0x0 0x84 0x5f 0xff 0x1f 0x1 0x0 0x0 0x6 0x84 0x9f 0x0 0x1f 0x1 0x0 0x0
|
||||||
|
0x6b 0x1 0x84 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x85 0x62 0xff 0xf 0x1 0x0 0x0
|
||||||
|
0x6c 0x6 0x85 0x9f 0x0 0xf 0x1 0x0 0x0 0x0 0x86 0x6a 0xff 0xf8 0x0 0x0 0x0
|
||||||
|
0x6d 0x6 0x86 0x9f 0x0 0xf8 0x0 0x0 0x0 0x1 0x87 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6e 0x0 0x87 0xd6 0xfe 0xca 0x1 0x0 0x0 0x6 0x87 0x9f 0x0 0xca 0x1 0x0 0x0
|
||||||
|
0x6f 0x1 0x88 0x4b 0x0 0x0 0x0 0x0 0x0 0x0 0x88 0xba 0xff 0x7d 0x0 0x0 0x0
|
||||||
|
0x70 0x6 0x88 0x8c 0x0 0x7d 0x0 0x0 0x0 0x0 0x89 0xc1 0xff 0x96 0x0 0x0 0x0
|
||||||
|
0x71 0x6 0x89 0x8c 0x0 0x96 0x0 0x0 0x0 0x1 0x89 0x4c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x72 0x0 0x8a 0xc5 0xff 0xb1 0x0 0x0 0x0 0x6 0x8a 0x8c 0x0 0xb1 0x0 0x0 0x0
|
||||||
|
0x73 0x0 0x8b 0xcf 0xff 0xbf 0x0 0x0 0x0 0x6 0x8b 0x8c 0x0 0xbf 0x0 0x0 0x0
|
||||||
|
0x74 0x0 0x8c 0xda 0xff 0xce 0x0 0x0 0x0 0x6 0x8c 0x8c 0x0 0xce 0x0 0x0 0x0
|
||||||
|
0x75 0x1 0x8d 0x47 0x0 0x0 0x0 0x0 0x0 0x0 0x8d 0xd6 0xff 0xd0 0x0 0x0 0x0
|
||||||
|
0x76 0x6 0x8d 0x8c 0x0 0xd0 0x0 0x0 0x0 0x0 0x8e 0xd8 0xff 0xd6 0x0 0x0 0x0
|
||||||
|
0x77 0x6 0x8e 0x8c 0x0 0xd6 0x0 0x0 0x0 0x1 0x8e 0x43 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x78 0x0 0x8f 0xe7 0xff 0xe3 0x0 0x0 0x0 0x6 0x8f 0x8c 0x0 0xe3 0x0 0x0 0x0
|
||||||
|
0x79 0x0 0x90 0xfe 0xff 0xee 0x0 0x1 0x0 0x6 0x90 0x8c 0x0 0xee 0x0 0x1 0x0
|
||||||
|
0x7a 0x1 0x90 0x41 0x0 0x0 0x0 0x0 0x0 0x0 0x91 0x10 0x0 0xf9 0x0 0x0 0x0
|
||||||
|
0x7b 0x6 0x91 0x8c 0x0 0xf9 0x0 0x0 0x0 0x1 0x92 0x3f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7c 0x0 0x92 0x17 0x0 0xe 0x1 0x0 0x0 0x6 0x92 0x8c 0x0 0xe 0x1 0x0 0x0
|
||||||
|
0x7d 0x1 0x93 0x45 0x0 0x0 0x0 0x0 0x0 0x0 0x93 0x1b 0x0 0x22 0x1 0x1 0x0
|
||||||
|
0x7e 0x6 0x93 0x8c 0x0 0x22 0x1 0x1 0x0 0x0 0x94 0x24 0x0 0x54 0x1 0x0 0x0
|
||||||
|
0x7f 0x6 0x94 0x8c 0x0 0x54 0x1 0x0 0x0 0x0 0x95 0x1c 0x0 0x33 0x1 0x0 0x0
|
||||||
|
0x80 0x6 0x95 0x8c 0x0 0x33 0x1 0x0 0x0 0x1 0x95 0x48 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x81 0x0 0x96 0x29 0x0 0x49 0x1 0x0 0x0 0x6 0x96 0x8c 0x0 0x49 0x1 0x0 0x0
|
||||||
|
0x82 0x1 0x96 0x47 0x0 0x0 0x0 0x0 0x0 0x0 0x97 0x2e 0x0 0x56 0x1 0x0 0x0
|
||||||
|
0x83 0x6 0x97 0x8c 0x0 0x56 0x1 0x0 0x0 0x1 0x98 0x4e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x84 0x0 0x98 0x2e 0x0 0x5f 0x1 0x0 0x0 0x6 0x98 0x77 0x0 0x5f 0x1 0x0 0x0
|
||||||
|
0x85 0x0 0x99 0x2a 0x0 0x86 0x1 0x0 0x0 0x6 0x99 0x77 0x0 0x86 0x1 0x0 0x0
|
||||||
|
0x86 0x4 0x99 0xbc 0x0 0x86 0x1 0x0 0x0 0x0 0x9a 0x21 0x0 0x5c 0x1 0x0 0x0
|
||||||
|
0x87 0x6 0x9a 0x77 0x0 0x5c 0x1 0x0 0x0 0x1 0x9a 0x4f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x88 0x0 0x9b 0x26 0x0 0x6e 0x1 0x0 0x0 0x6 0x9b 0x77 0x0 0x6e 0x1 0x0 0x0
|
||||||
|
0x89 0x1 0x9b 0x50 0x0 0x0 0x0 0x0 0x0 0x0 0x9c 0x2f 0x0 0x7d 0x1 0x0 0x0
|
||||||
|
0x8a 0x6 0x9c 0x77 0x0 0x7d 0x1 0x0 0x0 0x1 0x9d 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8b 0x0 0x9d 0x43 0x0 0x7f 0x1 0x0 0x0 0x6 0x9d 0x77 0x0 0x7f 0x1 0x0 0x0
|
||||||
|
0x8c 0x0 0x9e 0x92 0x0 0x82 0x1 0x0 0x0 0x6 0x9e 0x77 0x0 0x82 0x1 0x0 0x0
|
||||||
|
0x8d 0x1 0x9f 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x9f 0xba 0x0 0x87 0x1 0x0 0x0
|
||||||
|
0x8e 0x6 0x9f 0x77 0x0 0x87 0x1 0x0 0x0 0x0 0xa0 0xe4 0x0 0xae 0x1 0x0 0x0
|
||||||
|
0x8f 0x6 0xa0 0x77 0x0 0xae 0x1 0x0 0x0 0x1 0xa0 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x90 0x0 0xa1 0xd6 0x0 0x77 0x1 0x0 0x0 0x6 0xa1 0x63 0x0 0x77 0x1 0x0 0x0
|
||||||
|
0x91 0x1 0xa1 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0xa2 0xe5 0x0 0x81 0x1 0x0 0x0
|
||||||
|
0x92 0x6 0xa2 0x63 0x0 0x81 0x1 0x0 0x0 0x0 0xa3 0xeb 0x0 0x89 0x1 0x0 0x0
|
||||||
|
0x93 0x6 0xa3 0x63 0x0 0x89 0x1 0x0 0x0 0x1 0xa4 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x94 0x0 0xa4 0xf2 0x0 0x91 0x1 0x0 0x0 0x6 0xa4 0x63 0x0 0x91 0x1 0x0 0x0
|
||||||
|
0x95 0x0 0xa5 0xef 0x0 0x98 0x1 0x1 0x0 0x6 0xa5 0x63 0x0 0x98 0x1 0x1 0x0
|
||||||
|
0x96 0x1 0xa5 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0xa6 0xef 0x0 0x99 0x1 0x0 0x0
|
||||||
|
0x97 0x6 0xa6 0x63 0x0 0x99 0x1 0x0 0x0 0x1 0xa6 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x98 0x0 0xa7 0xed 0x0 0x9a 0x1 0x0 0x0 0x6 0xa7 0x63 0x0 0x9a 0x1 0x0 0x0
|
||||||
|
0x99 0x5 0xa7 0xf0 0x0 0x9a 0x1 0x0 0x0 0x0 0xa8 0xec 0x0 0x9a 0x1 0x0 0x0
|
||||||
|
0x9a 0x6 0xa8 0x63 0x0 0x9a 0x1 0x0 0x0 0x1 0xa9 0x4d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9b 0x0 0xa9 0xa 0x1 0xc2 0x1 0x0 0x0 0x6 0xa9 0x63 0x0 0xc2 0x1 0x0 0x0
|
||||||
|
0x9c 0x1 0xaa 0x49 0x0 0x0 0x0 0x0 0x0 0x0 0xaa 0xeb 0x0 0x86 0x1 0x0 0x0
|
||||||
|
0x9d 0x6 0xaa 0x63 0x0 0x86 0x1 0x0 0x0 0x0 0xab 0x9 0x1 0xb5 0x1 0x0 0x0
|
||||||
|
0x9e 0x6 0xab 0x63 0x0 0xb5 0x1 0x0 0x0 0x1 0xab 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9f 0x0 0xac 0xe9 0x0 0x7d 0x1 0x0 0x0 0x6 0xac 0x63 0x0 0x7d 0x1 0x0 0x0
|
||||||
|
0xa0 0x0 0xad 0xf1 0x0 0x89 0x1 0x0 0x0 0x6 0xad 0x50 0x0 0x89 0x1 0x0 0x0
|
||||||
|
0xa1 0x1 0xad 0x51 0x0 0x0 0x0 0x0 0x0 0x0 0xae 0xf1 0x0 0x8f 0x1 0x0 0x0
|
||||||
|
0xa2 0x6 0xae 0x50 0x0 0x8f 0x1 0x0 0x0 0x1 0xaf 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa3 0x0 0xaf 0x7 0x1 0xb8 0x1 0x0 0x0 0x6 0xaf 0x50 0x0 0xb8 0x1 0x0 0x0
|
||||||
|
0xa4 0x0 0xb0 0xf7 0x0 0xa1 0x1 0x0 0x0 0x6 0xb0 0x50 0x0 0xa1 0x1 0x0 0x0
|
||||||
|
0xa5 0x1 0xb0 0x51 0x0 0x0 0x0 0x0 0x0 0x0 0xb1 0xd5 0x0 0x6c 0x1 0x0 0x0
|
||||||
|
0xa6 0x6 0xb1 0x50 0x0 0x6c 0x1 0x0 0x0 0x0 0xb2 0xf4 0x0 0x9e 0x1 0x0 0x0
|
||||||
|
0xa7 0x6 0xb2 0x50 0x0 0x9e 0x1 0x0 0x0 0x1 0xb2 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa8 0x0 0xb3 0xed 0x0 0x92 0x1 0x0 0x0 0x6 0xb3 0x50 0x0 0x92 0x1 0x0 0x0
|
||||||
|
0xa9 0x1 0xb3 0x57 0x0 0x0 0x0 0x0 0x0 0x0 0xb4 0xd5 0x0 0x69 0x1 0x0 0x0
|
||||||
|
0xaa 0x6 0xb4 0x50 0x0 0x69 0x1 0x0 0x0 0x1 0xb5 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xab 0x0 0xb5 0xe2 0x0 0x7f 0x1 0x0 0x0 0x6 0xb5 0x50 0x0 0x7f 0x1 0x0 0x0
|
||||||
|
0xac 0x0 0xb6 0xde 0x0 0x80 0x1 0x0 0x0 0x6 0xb6 0x50 0x0 0x80 0x1 0x0 0x0
|
||||||
|
0xad 0x0 0xb7 0xe1 0x0 0x83 0x1 0x0 0x0 0x6 0xb7 0x50 0x0 0x83 0x1 0x0 0x0
|
||||||
|
0xae 0x0 0xb8 0xdd 0x0 0x7b 0x1 0x0 0x0 0x6 0xb8 0x50 0x0 0x7b 0x1 0x0 0x0
|
||||||
|
0xaf 0x1 0xb8 0x54 0x0 0x0 0x0 0x0 0x0 0x0 0xb9 0xf2 0x0 0x9c 0x1 0x0 0x0
|
||||||
|
0xb0 0x6 0xb9 0x50 0x0 0x9c 0x1 0x0 0x0 0x1 0xba 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb1 0x0 0xba 0xd6 0x0 0x61 0x1 0x0 0x0 0x6 0xba 0x50 0x0 0x61 0x1 0x0 0x0
|
||||||
|
0xb2 0x0 0xbb 0xf8 0x0 0x94 0x1 0x0 0x0 0x6 0xbb 0x50 0x0 0x94 0x1 0x0 0x0
|
||||||
|
0xb3 0x0 0xbc 0xd7 0x0 0x60 0x1 0x0 0x0 0x6 0xbc 0x50 0x0 0x60 0x1 0x0 0x0
|
||||||
|
0xb4 0x0 0xbd 0xfb 0x0 0x96 0x1 0x0 0x0 0x6 0xbd 0x50 0x0 0x96 0x1 0x0 0x0
|
||||||
|
0xb5 0x0 0xbe 0xf2 0x0 0x8c 0x1 0x0 0x0 0x6 0xbe 0x50 0x0 0x8c 0x1 0x0 0x0
|
||||||
|
0xb6 0x1 0xbe 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xbf 0xd6 0x0 0x61 0x1 0x0 0x0
|
||||||
|
0xb7 0x6 0xbf 0x50 0x0 0x61 0x1 0x0 0x0 0x0 0xc0 0xe0 0x0 0x73 0x1 0x0 0x0
|
||||||
|
0xb8 0x6 0xc0 0x50 0x0 0x73 0x1 0x0 0x0 0x0 0xc1 0xe1 0x0 0x78 0x1 0x0 0x0
|
||||||
|
0xb9 0x6 0xc1 0x50 0x0 0x78 0x1 0x0 0x0 0x0 0xc2 0xe1 0x0 0x77 0x1 0x0 0x0
|
||||||
|
0xba 0x6 0xc2 0x50 0x0 0x77 0x1 0x0 0x0 0x1 0xc2 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xbb 0x0 0xc3 0xe0 0x0 0x75 0x1 0x0 0x0 0x6 0xc3 0x50 0x0 0x75 0x1 0x0 0x0
|
||||||
|
0xbc 0x1 0xc3 0x5b 0x0 0x0 0x0 0x0 0x0 0x0 0xc4 0xe3 0x0 0x7d 0x1 0x0 0x0
|
||||||
|
0xbd 0x6 0xc4 0x50 0x0 0x7d 0x1 0x0 0x0 0x0 0xc5 0xe5 0x0 0x7f 0x1 0x0 0x0
|
||||||
|
0xbe 0x6 0xc5 0x50 0x0 0x7f 0x1 0x0 0x0 0x1 0xc6 0x5c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xbf 0x0 0xc6 0xe4 0x0 0x7e 0x1 0x0 0x0 0x6 0xc6 0x50 0x0 0x7e 0x1 0x0 0x0
|
||||||
|
0xc0 0x0 0xc7 0xe5 0x0 0x7f 0x1 0x0 0x0 0x6 0xc7 0x50 0x0 0x7f 0x1 0x0 0x0
|
||||||
|
0xc1 0x1 0xc7 0x5d 0x0 0x0 0x0 0x0 0x0 0x0 0xc8 0xfb 0x0 0xa6 0x1 0x0 0x0
|
||||||
|
0xc2 0x6 0xc8 0x50 0x0 0xa6 0x1 0x0 0x0 0x1 0xc8 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc3 0x0 0xc9 0xd0 0x0 0x6e 0x1 0x0 0x0 0x6 0xc9 0x50 0x0 0x6e 0x1 0x0 0x0
|
||||||
|
0xc4 0x0 0xca 0xdc 0x0 0x7a 0x1 0x0 0x0 0x6 0xca 0x50 0x0 0x7a 0x1 0x0 0x0
|
||||||
|
0xc5 0x1 0xcb 0x5f 0x0 0x0 0x0 0x0 0x0 0x0 0xcb 0xe0 0x0 0x7d 0x1 0x0 0x0
|
||||||
|
0xc6 0x6 0xcb 0x50 0x0 0x7d 0x1 0x0 0x0 0x1 0xcc 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc7 0x0 0xcc 0xe2 0x0 0x7f 0x1 0x0 0x0 0x6 0xcc 0x50 0x0 0x7f 0x1 0x0 0x0
|
||||||
|
0xc8 0x0 0xcd 0xe4 0x0 0x80 0x1 0x0 0x0 0x6 0xcd 0x50 0x0 0x80 0x1 0x0 0x0
|
||||||
|
0xc9 0x1 0xcd 0x61 0x0 0x0 0x0 0x0 0x0 0x0 0xce 0xe4 0x0 0x81 0x1 0x0 0x0
|
||||||
|
0xca 0x6 0xce 0x50 0x0 0x81 0x1 0x0 0x0 0x0 0xcf 0xe2 0x0 0x7e 0x1 0x0 0x0
|
||||||
|
0xcb 0x6 0xcf 0x50 0x0 0x7e 0x1 0x0 0x0 0x1 0xd0 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xcc 0x0 0xd0 0xf6 0x0 0x9e 0x1 0x0 0x0 0x6 0xd0 0x50 0x0 0x9e 0x1 0x0 0x0
|
||||||
|
0xcd 0x0 0xd1 0xd1 0x0 0x60 0x1 0x0 0x0 0x6 0xd1 0x50 0x0 0x60 0x1 0x0 0x0
|
||||||
|
0xce 0x0 0xd2 0xd2 0x0 0x61 0x1 0x0 0x0 0x6 0xd2 0x50 0x0 0x61 0x1 0x0 0x0
|
||||||
|
0xcf 0x1 0xd2 0x5f 0x0 0x0 0x0 0x0 0x0 0x0 0xd3 0xd5 0x0 0x67 0x1 0x0 0x0
|
||||||
|
0xd0 0x6 0xd3 0x50 0x0 0x67 0x1 0x0 0x0 0x0 0xd4 0xec 0x0 0x8d 0x1 0x0 0x0
|
||||||
|
0xd1 0x6 0xd4 0x50 0x0 0x8d 0x1 0x0 0x0 0x1 0xd4 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd2 0x0 0xd5 0xc9 0x0 0x53 0x1 0x0 0x0 0x6 0xd5 0x50 0x0 0x53 0x1 0x0 0x0
|
||||||
|
0xd3 0x1 0xd6 0x5c 0x0 0x0 0x0 0x0 0x0 0x0 0xd6 0xcd 0x0 0x58 0x1 0x0 0x0
|
||||||
|
0xd4 0x6 0xd6 0x50 0x0 0x58 0x1 0x0 0x0 0x1 0xd7 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd5 0x0 0xd7 0xca 0x0 0x54 0x1 0x0 0x0 0x6 0xd7 0x50 0x0 0x54 0x1 0x0 0x0
|
||||||
|
0xd6 0x0 0xd8 0xd2 0x0 0x5e 0x1 0x0 0x0 0x6 0xd8 0x50 0x0 0x5e 0x1 0x0 0x0
|
||||||
|
0xd7 0x0 0xd9 0x2c 0x1 0x15 0x1 0x0 0x0 0x6 0xd9 0x50 0x0 0x15 0x1 0x0 0x0
|
||||||
|
0xd8 0x0 0xda 0x60 0x1 0x1c 0x1 0x0 0x0 0x6 0xda 0x50 0x0 0x1c 0x1 0x0 0x0
|
||||||
|
0xd9 0x1 0xda 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0xdb 0x5d 0x1 0xd6 0x0 0x0 0x0
|
||||||
|
0xda 0x6 0xdb 0x50 0x0 0xd6 0x0 0x0 0x0 0x4 0xdc 0x43 0x0 0xd6 0x0 0x0 0x0
|
||||||
|
0xdb 0x1 0xdc 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xdc 0x9c 0x1 0xc8 0x0 0x0 0x0
|
||||||
|
0xdc 0x6 0xdc 0x50 0x0 0xc8 0x0 0x0 0x0 0x0 0xdd 0x70 0x1 0x8e 0x0 0x0 0x0
|
||||||
|
0xdd 0x6 0xdd 0x50 0x0 0x8e 0x0 0x0 0x0 0x0 0xde 0x83 0x1 0x86 0x0 0x0 0x0
|
||||||
|
0xde 0x6 0xde 0x50 0x0 0x86 0x0 0x0 0x0 0x0 0xdf 0x93 0x1 0x86 0x0 0x0 0x0
|
||||||
|
0xdf 0x6 0xdf 0x50 0x0 0x86 0x0 0x0 0x0 0x1 0xdf 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe0 0x0 0xe0 0x74 0x1 0x7d 0x0 0x0 0x0 0x6 0xe0 0x50 0x0 0x7d 0x0 0x0 0x0
|
||||||
|
0xe1 0x0 0xe1 0x2d 0x1 0x7c 0x0 0x0 0x0 0x6 0xe1 0x50 0x0 0x7c 0x0 0x0 0x0
|
||||||
|
0xe2 0x0 0xe3 0xf0 0x0 0xa5 0x0 0xff 0xff 0x6 0xe3 0x50 0x0 0xa5 0x0 0xff 0xff
|
||||||
|
0xe3 0x1 0xe4 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xe4 0x73 0x0 0x99 0x0 0x0 0x0
|
||||||
|
0xe4 0x6 0xe4 0x50 0x0 0x99 0x0 0x0 0x0 0x0 0xe6 0x14 0x0 0xb5 0x0 0x0 0x0
|
||||||
|
0xe5 0x6 0xe6 0x50 0x0 0xb5 0x0 0x0 0x0 0x0 0xe8 0xfb 0xff 0xbf 0x0 0x0 0x0
|
||||||
|
0xe6 0x6 0xe8 0x50 0x0 0xbf 0x0 0x0 0x0 0x1 0xe9 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe7 0x0 0xea 0x8 0x0 0xd5 0x0 0x0 0x0 0x6 0xea 0x50 0x0 0xd5 0x0 0x0 0x0
|
||||||
|
0xe8 0x1 0xec 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xee 0x68 0x0 0xae 0x0 0x0 0x0
|
||||||
|
0xe9 0x6 0xee 0x64 0x0 0xae 0x0 0x0 0x0 0x0 0xf0 0xc5 0x0 0x5e 0x0 0x0 0x0
|
||||||
|
0xea 0x6 0xf0 0x64 0x0 0x5e 0x0 0x0 0x0 0x1 0xf1 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xeb 0x0 0xf2 0x1b 0x1 0x2f 0x0 0x1 0x0 0x6 0xf2 0x64 0x0 0x2f 0x0 0x1 0x0
|
||||||
|
0xec 0x1 0xf2 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0xf3 0x15 0x1 0x15 0x0 0x0 0x0
|
||||||
|
0xed 0x6 0xf3 0x64 0x0 0x15 0x0 0x0 0x0 0x0 0xf4 0x2a 0x1 0x8 0x0 0x0 0x0
|
||||||
|
0xee 0x6 0xf4 0x76 0x0 0x8 0x0 0x0 0x0 0x1 0xf5 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xef 0x0 0xf5 0x6c 0x1 0x13 0x0 0x0 0x0 0x6 0xf5 0x76 0x0 0x13 0x0 0x0 0x0
|
||||||
|
0xf0 0x0 0xf6 0x63 0x1 0xa 0x0 0x0 0x0 0x6 0xf6 0x76 0x0 0xa 0x0 0x0 0x0
|
||||||
|
0xf1 0x0 0xf7 0x8d 0x1 0x2 0x0 0x0 0x0 0x6 0xf7 0x76 0x0 0x2 0x0 0x0 0x0
|
||||||
|
0xf2 0x1 0xf7 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0xf8 0xa5 0x1 0xf7 0xff 0x0 0x0
|
||||||
|
0xf3 0x6 0xf8 0x76 0x0 0xf7 0xff 0x0 0x0 0x0 0xf9 0x22 0x2 0xd6 0xff 0x0 0x0
|
||||||
|
0xf4 0x6 0xf9 0x76 0x0 0xd6 0xff 0x0 0x0 0x1 0xfa 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf5 0x0 0xfa 0x1 0x2 0xdf 0xff 0x0 0x0 0x6 0xfa 0x76 0x0 0xdf 0xff 0x0 0x0
|
||||||
|
0xf6 0x1 0xfb 0x54 0x0 0x0 0x0 0x0 0x0 0x0 0xfb 0xd2 0x1 0xe8 0xff 0x0 0x0
|
||||||
|
0xf7 0x6 0xfb 0x76 0x0 0xe8 0xff 0x0 0x0 0x0 0xfc 0xaf 0x1 0xf4 0xff 0x0 0x0
|
||||||
|
0xf8 0x6 0xfc 0x76 0x0 0xf4 0xff 0x0 0x0 0x1 0xfc 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf9 0x0 0xfd 0x93 0x1 0x4 0x0 0x0 0x0 0x6 0xfd 0x76 0x0 0x4 0x0 0x0 0x0
|
||||||
|
0xfa 0x0 0xfe 0x8a 0x1 0x7 0x0 0x0 0x0 0x6 0xfe 0x76 0x0 0x7 0x0 0x0 0x0
|
||||||
|
0xfb 0x0 0xff 0x6f 0x1 0x7 0x0 0x0 0x0 0x6 0xff 0x76 0x0 0x7 0x0 0x0 0x0
|
||||||
|
0xfc 0x1 0x0 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x5a 0x1 0x5 0x0 0x0 0x0
|
||||||
|
0xfd 0x6 0x0 0x76 0x0 0x5 0x0 0x0 0x0 0x1 0x1 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfe 0x0 0x1 0x22 0x1 0x1 0x0 0x0 0x0 0x6 0x1 0x76 0x0 0x1 0x0 0x0 0x0
|
||||||
|
0xff 0x0 0x3 0x20 0x1 0x5 0x0 0x0 0x0 0x6 0x3 0x76 0x0 0x5 0x0 0x0 0x0
|
||||||
|
0x0 0x1 0x3 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0x4 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1 0x0 0x8 0xfe 0x0 0x1b 0x0 0x0 0x0 0x6 0x8 0x76 0x0 0x1b 0x0 0x0 0x0
|
||||||
|
0x2 0x1 0x9 0x59 0x0 0x0 0x0 0x0 0x0 0x1 0xe 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3 0x0 0xf 0xc0 0x0 0x53 0x0 0x0 0x0 0x6 0xf 0xa5 0x0 0x53 0x0 0x0 0x0
|
||||||
|
0x4 0x0 0x11 0x5d 0x0 0x7f 0x0 0x0 0x0 0x6 0x11 0xa5 0x0 0x7f 0x0 0x0 0x0
|
||||||
|
0x5 0x1 0x15 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0x16 0x16 0x0 0xb7 0x0 0x0 0x0
|
||||||
|
0x6 0x6 0x16 0xb9 0x0 0xb7 0x0 0x0 0x0 0x1 0x16 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7 0x0 0x16 0x1 0x0 0xa4 0x0 0x0 0x0 0x6 0x16 0xb9 0x0 0xa4 0x0 0x0 0x0
|
||||||
|
0x8 0x0 0x17 0x14 0x0 0xe6 0x0 0x0 0x0 0x6 0x17 0xb9 0x0 0xe6 0x0 0x0 0x0
|
||||||
|
0x9 0x1 0x17 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0x18 0x14 0x0 0xff 0x0 0x0 0x0
|
||||||
|
0xa 0x6 0x18 0xb9 0x0 0xff 0x0 0x0 0x0 0x1 0x19 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb 0x0 0x19 0xd 0x0 0xe3 0x0 0x0 0x0 0x6 0x19 0xb9 0x0 0xe3 0x0 0x0 0x0
|
||||||
|
0xc 0x0 0x1a 0xe 0x0 0xef 0x0 0xff 0xff 0x6 0x1a 0xb9 0x0 0xef 0x0 0xff 0xff
|
||||||
|
0xd 0x0 0x1b 0x13 0x0 0xe5 0x0 0x0 0x0 0x6 0x1b 0xb9 0x0 0xe5 0x0 0x0 0x0
|
||||||
|
0xe 0x0 0x1c 0xc 0x0 0xca 0x0 0x0 0x0 0x6 0x1c 0xb9 0x0 0xca 0x0 0x0 0x0
|
||||||
|
0xf 0x0 0x1d 0xff 0xff 0xc4 0x0 0x0 0x0 0x6 0x1d 0xb9 0x0 0xc4 0x0 0x0 0x0
|
||||||
|
0x10 0x1 0x1d 0x56 0x0 0x0 0x0 0x0 0x0 0x0 0x1e 0x9 0x0 0xe2 0x0 0x0 0x0
|
||||||
|
0x11 0x6 0x1e 0xb9 0x0 0xe2 0x0 0x0 0x0 0x1 0x1f 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x12 0x0 0x1f 0xc 0x0 0xd7 0x0 0x0 0x0 0x6 0x1f 0xa6 0x0 0xd7 0x0 0x0 0x0
|
||||||
|
0x13 0x0 0x20 0x11 0x0 0xd2 0x0 0x0 0x0 0x6 0x20 0xa6 0x0 0xd2 0x0 0x0 0x0
|
||||||
|
0x14 0x0 0x21 0x12 0x0 0xb7 0x0 0x0 0x0 0x6 0x21 0xa6 0x0 0xb7 0x0 0x0 0x0
|
||||||
|
0x15 0x0 0x22 0xc 0x0 0xc2 0x0 0x0 0x0 0x6 0x22 0xa6 0x0 0xc2 0x0 0x0 0x0
|
||||||
|
0x16 0x1 0x22 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x23 0x6 0x0 0xc5 0x0 0x0 0x0
|
||||||
|
0x17 0x6 0x23 0xa6 0x0 0xc5 0x0 0x0 0x0 0x1 0x23 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x18 0x0 0x24 0xff 0xff 0xc9 0x0 0x0 0x0 0x6 0x24 0xa6 0x0 0xc9 0x0 0x0 0x0
|
||||||
|
0x19 0x1 0x25 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x25 0xfe 0xff 0xdf 0x0 0x0 0x0
|
||||||
|
0x1a 0x6 0x25 0xa6 0x0 0xdf 0x0 0x0 0x0 0x0 0x26 0x4 0x0 0xc2 0x0 0x0 0x0
|
||||||
|
0x1b 0x6 0x26 0xa6 0x0 0xc2 0x0 0x0 0x0 0x0 0x27 0x8 0x0 0xc2 0x0 0x0 0x0
|
||||||
|
0x1c 0x6 0x27 0xa6 0x0 0xc2 0x0 0x0 0x0 0x1 0x27 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1d 0x0 0x28 0xe 0x0 0xd7 0x0 0x0 0x0 0x6 0x28 0xa6 0x0 0xd7 0x0 0x0 0x0
|
||||||
|
0x1e 0x0 0x29 0x10 0x0 0xbb 0x0 0x0 0x0 0x6 0x29 0xa6 0x0 0xbb 0x0 0x0 0x0
|
||||||
|
0x1f 0x1 0x29 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x2a 0x11 0x0 0xc4 0x0 0x0 0x0
|
||||||
|
0x20 0x6 0x2a 0xa6 0x0 0xc4 0x0 0x0 0x0 0x0 0x2b 0x13 0x0 0xd5 0x0 0x0 0x0
|
||||||
|
0x21 0x6 0x2b 0xa6 0x0 0xd5 0x0 0x0 0x0 0x1 0x2c 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x22 0x0 0x2c 0xe 0x0 0xb6 0x0 0x0 0x0 0x6 0x2c 0xa6 0x0 0xb6 0x0 0x0 0x0
|
||||||
|
0x23 0x0 0x2d 0x9 0x0 0xbc 0x0 0x0 0x0 0x6 0x2d 0xa6 0x0 0xbc 0x0 0x0 0x0
|
||||||
|
0x24 0x0 0x2e 0x5 0x0 0xbb 0x0 0x0 0x0 0x6 0x2e 0xa6 0x0 0xbb 0x0 0x0 0x0
|
||||||
|
0x25 0x0 0x2f 0x3 0x0 0xd5 0x0 0x0 0x0 0x6 0x2f 0xa6 0x0 0xd5 0x0 0x0 0x0
|
||||||
|
0x26 0x0 0x30 0xfd 0xff 0xd6 0x0 0x0 0x0 0x6 0x30 0xa6 0x0 0xd6 0x0 0x0 0x0
|
||||||
|
0x27 0x1 0x31 0x55 0x0 0x0 0x0 0x0 0x0 0x0 0x31 0xfc 0xff 0xbe 0x0 0x0 0x0
|
||||||
|
0x28 0x6 0x31 0x94 0x0 0xbe 0x0 0x0 0x0 0x0 0x32 0xfd 0xff 0xcd 0x0 0x0 0x0
|
||||||
|
0x29 0x6 0x32 0x94 0x0 0xcd 0x0 0x0 0x0 0x1 0x32 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2a 0x0 0x33 0xfc 0xff 0xd7 0x0 0x0 0x0 0x6 0x33 0x94 0x0 0xd7 0x0 0x0 0x0
|
||||||
|
0x2b 0x0 0x34 0xfb 0xff 0xc8 0x0 0xff 0xff 0x6 0x34 0x94 0x0 0xc8 0x0 0xff 0xff
|
||||||
|
0x2c 0x0 0x35 0xff 0xff 0xb4 0x0 0x0 0x0 0x6 0x35 0x94 0x0 0xb4 0x0 0x0 0x0
|
||||||
|
0x2d 0x1 0x36 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0x37 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2e 0x0 0x37 0xf8 0xff 0xb6 0x0 0x0 0x0 0x6 0x37 0x94 0x0 0xb6 0x0 0x0 0x0
|
||||||
|
0x2f 0x1 0x38 0x59 0x0 0x0 0x0 0x0 0x0 0x0 0x39 0xf9 0xff 0xa1 0x0 0x0 0x0
|
||||||
|
0x30 0x6 0x39 0x94 0x0 0xa1 0x0 0x0 0x0 0x1 0x3a 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x31 0x1 0x3c 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0x3d 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x32 0x0 0x3d 0xd 0x0 0x94 0x0 0x0 0x0 0x6 0x3d 0x94 0x0 0x94 0x0 0x0 0x0
|
||||||
|
0x33 0x1 0x40 0x62 0x0 0x0 0x0 0x0 0x0 0x1 0x42 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x34 0x1 0x44 0x68 0x0 0x0 0x0 0x0 0x0 0x0 0x45 0xbf 0xff 0x84 0x0 0x0 0x0
|
||||||
|
0x35 0x6 0x45 0xc0 0x0 0x84 0x0 0x0 0x0 0x1 0x45 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x36 0x1 0x47 0x66 0x0 0x0 0x0 0x0 0x0 0x0 0x47 0x74 0xff 0x56 0x0 0x0 0x0
|
||||||
|
0x37 0x6 0x47 0xdb 0x0 0x56 0x0 0x0 0x0 0x0 0x49 0xd7 0xfe 0x3a 0x0 0x0 0x0
|
||||||
|
0x38 0x6 0x49 0xdb 0x0 0x3a 0x0 0x0 0x0 0x1 0x49 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x39 0x0 0x4a 0xa 0xff 0x60 0x0 0x0 0x0 0x6 0x4a 0xf1 0x0 0x60 0x0 0x0 0x0
|
||||||
|
0x3a 0x1 0x4b 0x61 0x0 0x0 0x0 0x0 0x0 0x0 0x4c 0xdd 0xfe 0x3f 0x0 0x0 0x0
|
||||||
|
0x3b 0x6 0x4c 0xf1 0x0 0x3f 0x0 0x0 0x0 0x1 0x4e 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3c 0x0 0x4e 0xd6 0xfe 0x3d 0x0 0x0 0x0 0x6 0x4e 0xf1 0x0 0x3d 0x0 0x0 0x0
|
||||||
|
0x3d 0x1 0x4f 0x59 0x0 0x0 0x0 0x0 0x0 0x0 0x50 0xf6 0xfe 0x24 0x0 0x0 0x0
|
||||||
|
0x3e 0x6 0x50 0xf1 0x0 0x24 0x0 0x0 0x0 0x1 0x50 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3f 0x0 0x52 0x8 0xff 0x26 0x0 0x0 0x0 0x6 0x52 0xf1 0x0 0x26 0x0 0x0 0x0
|
||||||
|
0x40 0x1 0x53 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0x54 0x4e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x41 0x0 0x55 0x7 0xff 0x40 0x0 0x0 0x0 0x6 0x55 0xf1 0x0 0x40 0x0 0x0 0x0
|
||||||
|
0x42 0x1 0x55 0x4f 0x0 0x0 0x0 0x0 0x0 0x0 0x57 0xe 0xff 0x20 0x0 0x0 0x0
|
||||||
|
0x43 0x6 0x57 0x6 0x1 0x20 0x0 0x0 0x0 0x1 0x58 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x44 0x0 0x59 0xb5 0xfe 0x12 0x0 0x0 0x0 0x6 0x59 0x6 0x1 0x12 0x0 0x0 0x0
|
||||||
|
0x45 0x0 0x5a 0xc4 0xfe 0xb 0x0 0x0 0x0 0x6 0x5a 0x6 0x1 0xb 0x0 0x0 0x0
|
||||||
|
0x46 0x1 0x5a 0x53 0x0 0x0 0x0 0x0 0x0 0x0 0x5b 0xbb 0xfe 0xb 0x0 0x2 0x0
|
||||||
|
0x47 0x6 0x5b 0x6 0x1 0xb 0x0 0x2 0x0 0x0 0x5c 0xac 0xfe 0xd 0x0 0x0 0x0
|
||||||
|
0x48 0x6 0x5c 0x6 0x1 0xd 0x0 0x0 0x0 0x1 0x5c 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x49 0x0 0x5d 0x2c 0xfe 0x1a 0x0 0x0 0x0 0x6 0x5d 0x6 0x1 0x1a 0x0 0x0 0x0
|
||||||
|
0x4a 0x1 0x5e 0x56 0x0 0x0 0x0 0x0 0x0 0x0 0x5e 0x44 0xfe 0x22 0x0 0x0 0x0
|
||||||
|
0x4b 0x6 0x5e 0xf2 0x0 0x22 0x0 0x0 0x0 0x1 0x5f 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4c 0x0 0x5f 0x76 0xfe 0x27 0x0 0x0 0x0 0x6 0x5f 0xf2 0x0 0x27 0x0 0x0 0x0
|
||||||
|
0x4d 0x0 0x60 0xa2 0xfe 0x26 0x0 0x0 0x0 0x6 0x60 0xf2 0x0 0x26 0x0 0x0 0x0
|
||||||
|
0x4e 0x0 0x61 0xd2 0xfe 0x1d 0x0 0x0 0x0 0x6 0x61 0xd9 0x0 0x1d 0x0 0x0 0x0
|
||||||
|
0x4f 0x1 0x62 0x54 0x0 0x0 0x0 0x0 0x0 0x0 0x63 0xc6 0xfe 0x19 0x0 0x0 0x0
|
||||||
|
0x50 0x6 0x63 0xd9 0x0 0x19 0x0 0x0 0x0 0x1 0x64 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x51 0x1 0x66 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0x67 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x52 0x1 0x68 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0x6b 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x53 0x0 0x6b 0x2c 0xff 0x4a 0x0 0x0 0x0 0x6 0x6b 0xf3 0x0 0x4a 0x0 0x0 0x0
|
||||||
|
0x54 0x1 0x6d 0x5b 0x0 0x0 0x0 0x0 0x0 0x1 0x6e 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x55 0x1 0x73 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0x74 0xe5 0xfe 0x37 0x0 0x0 0x0
|
||||||
|
0x56 0x6 0x74 0x3a 0x1 0x37 0x0 0x0 0x0 0x1 0x75 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x57 0x1 0x76 0x58 0x0 0x0 0x0 0x0 0x0 0x0 0x77 0xee 0xfe 0x5 0x0 0x0 0x0
|
||||||
|
0x58 0x6 0x77 0x56 0x1 0x5 0x0 0x0 0x0 0x1 0x78 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x59 0x1 0x7a 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0x7c 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5a 0x1 0x80 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x81 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5b 0x1 0x84 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0x84 0xf 0x0 0xf8 0xff 0x0 0x0
|
||||||
|
0x5c 0x6 0x84 0xfc 0x1 0xf8 0xff 0x0 0x0 0x1 0x85 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5d 0x1 0x86 0x5a 0x0 0x0 0x0 0x0 0x0 0x0 0x86 0x9e 0x0 0xeb 0xff 0x0 0x0
|
||||||
|
0x5e 0x6 0x86 0x13 0x2 0xeb 0xff 0x0 0x0 0x1 0x88 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5f 0x0 0x89 0xbf 0x0 0xf0 0xff 0x0 0x0 0x6 0x89 0x13 0x2 0xf0 0xff 0x0 0x0
|
||||||
|
0x60 0x1 0x8a 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x8b 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x61 0x1 0x8d 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0x8e 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x62 0x0 0x91 0xea 0xff 0xf6 0xff 0x0 0x0 0x6 0x91 0x57 0x2 0xf6 0xff 0x0 0x0
|
||||||
|
0x63 0x1 0x92 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0x93 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x64 0x1 0x98 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x99 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x65 0x1 0x9c 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x9d 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x66 0x1 0xa1 0x60 0x0 0x0 0x0 0x0 0x0 0x1 0xa2 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x67 0x1 0xa3 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0xa5 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x68 0x1 0xaa 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0xad 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x69 0x1 0xaf 0x5f 0x0 0x0 0x0 0x0 0x0 0x1 0xb0 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6a 0x1 0xb1 0x5c 0x0 0x0 0x0 0x0 0x0 0x0 0xb3 0x85 0xff 0xfb 0xff 0x0 0x0
|
||||||
|
0x6b 0x6 0xb3 0xa8 0x6 0xfb 0xff 0x0 0x0 0x1 0xb4 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6c 0x1 0xb6 0x59 0x0 0x0 0x0 0x0 0x0 0x1 0xb9 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6d 0x1 0xba 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0xbe 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6e 0x1 0xbf 0x59 0x0 0x0 0x0 0x0 0x0 0x1 0xc0 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6f 0x1 0xc3 0x5b 0x0 0x0 0x0 0x0 0x0 0x0 0xc3 0x30 0x0 0xec 0xff 0x0 0x0
|
||||||
|
0x70 0x6 0xc3 0x0 0x0 0xec 0xff 0x0 0x0 0x1 0xc4 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x71 0x1 0xc7 0x5e 0x0 0x0 0x0 0x0 0x0 0x0 0xc8 0x8b 0x0 0xda 0xff 0x0 0x0
|
||||||
|
0x72 0x6 0xc8 0x0 0x0 0xda 0xff 0x0 0x0 0x1 0xc9 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x73 0x1 0xcc 0x5e 0x0 0x0 0x0 0x0 0x0 0x0 0xcc 0xc0 0x0 0xeb 0xff 0x0 0x0
|
||||||
|
0x74 0x6 0xcc 0xf0 0x6 0xeb 0xff 0x0 0x0 0x1 0xcf 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x75 0x0 0xd0 0xd8 0x0 0xeb 0xff 0x0 0x0 0x6 0xd0 0xc4 0x5 0xeb 0xff 0x0 0x0
|
||||||
|
0x76 0x1 0xd1 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0xd4 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x77 0x0 0xd4 0xe4 0x0 0xfd 0xff 0x0 0x0 0x6 0xd4 0xc 0x5 0xfd 0xff 0x0 0x0
|
||||||
|
0x78 0x1 0xd6 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0xd7 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x79 0x0 0xd7 0xed 0x0 0xf7 0xff 0x0 0x0 0x6 0xd7 0x82 0x4 0xf7 0xff 0x0 0x0
|
||||||
|
0x7a 0x1 0xd8 0x60 0x0 0x0 0x0 0x0 0x0 0x0 0xda 0xec 0x0 0xef 0xff 0x0 0x0
|
||||||
|
0x7b 0x6 0xda 0x1b 0x4 0xef 0xff 0x0 0x0 0x1 0xdb 0x62 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7c 0x1 0xdc 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0xdd 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7d 0x0 0xdd 0xeb 0x0 0xef 0xff 0x0 0x0 0x6 0xdd 0xa5 0x3 0xef 0xff 0x0 0x0
|
||||||
|
0x7e 0x1 0xe1 0x65 0x0 0x0 0x0 0x0 0x0 0x0 0xe1 0xff 0x0 0xef 0xff 0x0 0x0
|
||||||
|
0x7f 0x6 0xe1 0x52 0x3 0xef 0xff 0x0 0x0 0x1 0xe2 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x80 0x0 0xe5 0xe6 0x0 0xe3 0xff 0x0 0x0 0x6 0xe5 0x27 0x3 0xe3 0xff 0x0 0x0
|
||||||
|
0x81 0x1 0xe6 0x63 0x0 0x0 0x0 0x0 0x0 0x0 0xe9 0xfa 0x0 0xcc 0xff 0x0 0x0
|
||||||
|
0x82 0x6 0xe9 0x27 0x3 0xcc 0xff 0x0 0x0 0x1 0xeb 0x62 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x83 0x0 0xed 0xee 0x0 0xfa 0xff 0x0 0x0 0x6 0xed 0x14 0x3 0xfa 0xff 0x0 0x0
|
||||||
|
0x84 0x1 0xee 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0xf0 0x65 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x85 0x0 0xf2 0xfe 0x0 0xf 0x0 0x0 0x0 0x6 0xf2 0x14 0x3 0xf 0x0 0x0 0x0
|
||||||
|
0x86 0x1 0xf3 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0xf4 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x87 0x1 0xf6 0x69 0x0 0x0 0x0 0x0 0x0 0x0 0xf7 0xef 0x0 0xf3 0xff 0xfe 0xff
|
||||||
|
0x88 0x6 0xf7 0x14 0x3 0xf3 0xff 0xfe 0xff 0x1 0xf8 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x89 0x1 0xf9 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0xfa 0x6d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8a 0x0 0xfb 0xe6 0x0 0xd7 0xff 0x0 0x0 0x6 0xfb 0x14 0x3 0xd7 0xff 0x0 0x0
|
||||||
|
0x8b 0x1 0xfc 0x6f 0x0 0x0 0x0 0x0 0x0 0x1 0xfd 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8c 0x0 0xfe 0xe3 0x0 0xe6 0xff 0x0 0x0 0x6 0xfe 0x14 0x3 0xe6 0xff 0x0 0x0
|
||||||
|
0x8d 0x1 0xff 0x71 0x0 0x0 0x0 0x0 0x0 0x1 0x2 0x72 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8e 0x0 0x3 0xe7 0x0 0xda 0xff 0x0 0x0 0x6 0x3 0x14 0x3 0xda 0xff 0x0 0x0
|
||||||
|
0x8f 0x1 0x4 0x73 0x0 0x0 0x0 0x0 0x0 0x1 0x6 0x72 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x90 0x0 0x7 0xfb 0x0 0xfc 0xff 0x0 0x0 0x6 0x7 0x14 0x3 0xfc 0xff 0x0 0x0
|
||||||
|
0x91 0x1 0x7 0x71 0x0 0x0 0x0 0x0 0x0 0x1 0x8 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x92 0x0 0xb 0xee 0x0 0xd 0x0 0x0 0x0 0x6 0xb 0x14 0x3 0xd 0x0 0x0 0x0
|
||||||
|
0x93 0x1 0xb 0x71 0x0 0x0 0x0 0x0 0x0 0x1 0xc 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x94 0x1 0xd 0x6f 0x0 0x0 0x0 0x0 0x0 0x0 0xe 0xef 0x0 0x13 0x0 0x0 0x0
|
||||||
|
0x95 0x6 0xe 0x14 0x3 0x13 0x0 0x0 0x0 0x1 0x10 0x71 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x96 0x1 0x11 0x70 0x0 0x0 0x0 0x0 0x0 0x1 0x12 0x71 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x97 0x0 0x14 0x6 0x1 0xf1 0xff 0x0 0x0 0x6 0x14 0x1 0x3 0xf1 0xff 0x0 0x0
|
||||||
|
0x98 0x1 0x15 0x72 0x0 0x0 0x0 0x0 0x0 0x1 0x17 0x73 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x99 0x0 0x18 0x7 0x1 0xa 0x0 0xff 0xff 0x6 0x18 0x1 0x3 0xa 0x0 0xff 0xff
|
||||||
|
0x9a 0x5 0x18 0x71 0x1 0xa 0x0 0xff 0xff 0x1 0x1b 0x75 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9b 0x0 0x1b 0x1 0x1 0x7 0x0 0x0 0x0 0x6 0x1b 0xd2 0x2 0x7 0x0 0x0 0x0
|
||||||
|
0x9c 0x1 0x1c 0x74 0x0 0x0 0x0 0x0 0x0 0x0 0x1f 0xc 0x1 0x4 0x0 0x0 0x0
|
||||||
|
0x9d 0x6 0x1f 0xba 0x2 0x4 0x0 0x0 0x0 0x1 0x1f 0x76 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9e 0x1 0x21 0x75 0x0 0x0 0x0 0x0 0x0 0x1 0x23 0x76 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9f 0x0 0x24 0xc7 0x0 0xb4 0xff 0x0 0x0 0x6 0x24 0xba 0x2 0xb4 0xff 0x0 0x0
|
||||||
|
0xa0 0x1 0x24 0x75 0x0 0x0 0x0 0x0 0x0 0x0 0x27 0x78 0x0 0x8a 0xff 0x0 0x0
|
||||||
|
0xa1 0x6 0x27 0xba 0x2 0x8a 0xff 0x0 0x0 0x1 0x28 0x74 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa2 0x1 0x29 0x73 0x0 0x0 0x0 0x0 0x0 0x0 0x2a 0x4b 0x0 0x7a 0xff 0x0 0x0
|
||||||
|
0xa3 0x6 0x2a 0xba 0x2 0x7a 0xff 0x0 0x0 0x1 0x2a 0x72 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa4 0x0 0x2d 0x37 0x0 0x6d 0xff 0x0 0x0 0x6 0x2d 0xa1 0x2 0x6d 0xff 0x0 0x0
|
||||||
|
0xa5 0x1 0x2d 0x71 0x0 0x0 0x0 0x0 0x0 0x1 0x2e 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa6 0x0 0x30 0x34 0x0 0x67 0xff 0x0 0x0 0x6 0x30 0x85 0x2 0x67 0xff 0x0 0x0
|
||||||
|
0xa7 0x1 0x32 0x6f 0x0 0x0 0x0 0x0 0x0 0x0 0x33 0x35 0x0 0x61 0xff 0x0 0x0
|
||||||
|
0xa8 0x6 0x33 0x70 0x2 0x61 0xff 0x0 0x0 0x1 0x33 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xa9 0x0 0x36 0x26 0x0 0x6a 0xff 0x0 0x0 0x6 0x36 0x5e 0x2 0x6a 0xff 0x0 0x0
|
||||||
|
0xaa 0x1 0x37 0x6f 0x0 0x0 0x0 0x0 0x0 0x0 0x39 0x28 0x0 0x68 0xff 0x0 0x0
|
||||||
|
0xab 0x6 0x39 0x4b 0x2 0x68 0xff 0x0 0x0 0x1 0x39 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xac 0x1 0x3b 0x6d 0x0 0x0 0x0 0x0 0x0 0x0 0x3c 0x24 0x0 0x66 0xff 0x0 0x0
|
||||||
|
0xad 0x6 0x3c 0x4b 0x2 0x66 0xff 0x0 0x0 0x1 0x3d 0x6b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xae 0x0 0x3f 0x26 0x0 0x66 0xff 0x0 0x0 0x6 0x3f 0x4b 0x2 0x66 0xff 0x0 0x0
|
||||||
|
0xaf 0x1 0x40 0x6a 0x0 0x0 0x0 0x0 0x0 0x1 0x41 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb0 0x0 0x42 0x1f 0x0 0x54 0xff 0x0 0x0 0x6 0x42 0x36 0x2 0x54 0xff 0x0 0x0
|
||||||
|
0xb1 0x1 0x43 0x67 0x0 0x0 0x0 0x0 0x0 0x0 0x45 0xf 0x0 0x4d 0xff 0x0 0x0
|
||||||
|
0xb2 0x6 0x45 0x36 0x2 0x4d 0xff 0x0 0x0 0x1 0x45 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb3 0x1 0x46 0x69 0x0 0x0 0x0 0x0 0x0 0x0 0x48 0xd 0x0 0x68 0xff 0x0 0x0
|
||||||
|
0xb4 0x6 0x48 0x23 0x2 0x68 0xff 0x0 0x0 0x0 0x4b 0x13 0x0 0x62 0xff 0x0 0x0
|
||||||
|
0xb5 0x6 0x4b 0x23 0x2 0x62 0xff 0x0 0x0 0x1 0x4b 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb6 0x1 0x4c 0x6c 0x0 0x0 0x0 0x0 0x0 0x0 0x4e 0x0 0x0 0x4d 0xff 0x0 0x0
|
||||||
|
0xb7 0x6 0x4e 0x23 0x2 0x4d 0xff 0x0 0x0 0x1 0x50 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xb8 0x0 0x51 0xf4 0xff 0x5b 0xff 0x0 0x0 0x6 0x51 0x23 0x2 0x5b 0xff 0x0 0x0
|
||||||
|
0xb9 0x1 0x51 0x6d 0x0 0x0 0x0 0x0 0x0 0x0 0x54 0x1 0x0 0x63 0xff 0x0 0x0
|
||||||
|
0xba 0x6 0x54 0x23 0x2 0x63 0xff 0x0 0x0 0x1 0x54 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xbb 0x1 0x55 0x6f 0x0 0x0 0x0 0x0 0x0 0x0 0x57 0xf6 0xff 0x6e 0xff 0x0 0x0
|
||||||
|
0xbc 0x6 0x57 0x23 0x2 0x6e 0xff 0x0 0x0 0x1 0x5a 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xbd 0x0 0x5c 0xe5 0xff 0x64 0xff 0x0 0x0 0x6 0x5c 0x36 0x2 0x64 0xff 0x0 0x0
|
||||||
|
0xbe 0x1 0x5d 0x71 0x0 0x0 0x0 0x0 0x0 0x0 0x5f 0x1a 0x0 0x71 0xff 0x0 0x0
|
||||||
|
0xbf 0x6 0x5f 0x4e 0x2 0x71 0xff 0x0 0x0 0x0 0x62 0xb 0x0 0x5c 0xff 0x0 0x0
|
||||||
|
0xc0 0x6 0x62 0x4e 0x2 0x5c 0xff 0x0 0x0 0x1 0x62 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc1 0x1 0x64 0x71 0x0 0x0 0x0 0x0 0x0 0x0 0x65 0xf1 0xff 0x5e 0xff 0x0 0x0
|
||||||
|
0xc2 0x6 0x65 0x4e 0x2 0x5e 0xff 0x0 0x0 0x1 0x65 0x72 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc3 0x1 0x67 0x70 0x0 0x0 0x0 0x0 0x0 0x0 0x68 0x2 0x0 0x67 0xff 0x0 0x0
|
||||||
|
0xc4 0x6 0x68 0x3b 0x2 0x67 0xff 0x0 0x0 0x1 0x68 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc5 0x0 0x6b 0x16 0x0 0x59 0xff 0x0 0x0 0x6 0x6b 0x3b 0x2 0x59 0xff 0x0 0x0
|
||||||
|
0xc6 0x1 0x6c 0x6f 0x0 0x0 0x0 0x0 0x0 0x0 0x6e 0x23 0x0 0x6c 0xff 0x0 0x0
|
||||||
|
0xc7 0x6 0x6e 0x3b 0x2 0x6c 0xff 0x0 0x0 0x1 0x71 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc8 0x0 0x72 0x3a 0x0 0x57 0xff 0x0 0x0 0x6 0x72 0x27 0x2 0x57 0xff 0x0 0x0
|
||||||
|
0xc9 0x1 0x72 0x70 0x0 0x0 0x0 0x0 0x0 0x0 0x75 0x16 0x0 0x5b 0xff 0x0 0x0
|
||||||
|
0xca 0x6 0x75 0x27 0x2 0x5b 0xff 0x0 0x0 0x1 0x76 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xcb 0x1 0x77 0x6e 0x0 0x0 0x0 0x0 0x0 0x0 0x78 0xf7 0xff 0x5b 0xff 0x0 0x0
|
||||||
|
0xcc 0x6 0x78 0x27 0x2 0x5b 0xff 0x0 0x0 0x4 0x78 0x9c 0x1 0x5b 0xff 0x0 0x0
|
||||||
|
0xcd 0x1 0x78 0x6d 0x0 0x0 0x0 0x0 0x0 0x0 0x7b 0xf2 0xff 0x6d 0xff 0x0 0x0
|
||||||
|
0xce 0x6 0x7b 0x27 0x2 0x6d 0xff 0x0 0x0 0x1 0x7c 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xcf 0x1 0x7d 0x6b 0x0 0x0 0x0 0x0 0x0 0x0 0x7e 0xef 0xff 0x64 0xff 0x0 0x0
|
||||||
|
0xd0 0x6 0x7e 0x27 0x2 0x64 0xff 0x0 0x0 0x1 0x7f 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd1 0x0 0x82 0xca 0xff 0x58 0xff 0x0 0x0 0x6 0x82 0x27 0x2 0x58 0xff 0x0 0x0
|
||||||
|
0xd2 0x1 0x82 0x69 0x0 0x0 0x0 0x0 0x0 0x1 0x84 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd3 0x0 0x86 0xce 0xff 0x57 0xff 0x0 0x0 0x6 0x86 0x27 0x2 0x57 0xff 0x0 0x0
|
||||||
|
0xd4 0x0 0x89 0xfe 0xff 0x65 0xff 0x0 0x0 0x6 0x89 0x27 0x2 0x65 0xff 0x0 0x0
|
||||||
|
0xd5 0x1 0x89 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x8a 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd6 0x1 0x8c 0x6d 0x0 0x0 0x0 0x0 0x0 0x0 0x8d 0x13 0x0 0x68 0xff 0x0 0x0
|
||||||
|
0xd7 0x6 0x8d 0x27 0x2 0x68 0xff 0x0 0x0 0x1 0x8e 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd8 0x1 0x8f 0x6b 0x0 0x0 0x0 0x0 0x0 0x0 0x91 0xf0 0xff 0x6b 0xff 0x0 0x0
|
||||||
|
0xd9 0x6 0x91 0x54 0x2 0x6b 0xff 0x0 0x0 0x0 0x94 0xee 0xff 0x6b 0xff 0x0 0x0
|
||||||
|
0xda 0x6 0x94 0x54 0x2 0x6b 0xff 0x0 0x0 0x1 0x94 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xdb 0x0 0x97 0xfc 0xff 0x6f 0xff 0x0 0x0 0x6 0x97 0x54 0x2 0x6f 0xff 0x0 0x0
|
||||||
|
0xdc 0x1 0x98 0x6d 0x0 0x0 0x0 0x0 0x0 0x1 0x99 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xdd 0x0 0x9a 0x11 0x0 0x6f 0xff 0x0 0x0 0x6 0x9a 0x54 0x2 0x6f 0xff 0x0 0x0
|
||||||
|
0xde 0x1 0x9a 0x70 0x0 0x0 0x0 0x0 0x0 0x1 0x9d 0x71 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xdf 0x0 0x9d 0x25 0x0 0x72 0xff 0x0 0x0 0x6 0x9d 0x54 0x2 0x72 0xff 0x0 0x0
|
||||||
|
0xe0 0x1 0x9e 0x72 0x0 0x0 0x0 0x0 0x0 0x0 0xa1 0xed 0xff 0x70 0xff 0x0 0x0
|
||||||
|
0xe1 0x6 0xa1 0x54 0x2 0x70 0xff 0x0 0x0 0x1 0xa2 0x73 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe2 0x1 0xa3 0x74 0x0 0x0 0x0 0x0 0x0 0x1 0xa4 0x73 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe3 0x1 0xa6 0x72 0x0 0x0 0x0 0x0 0x0 0x1 0xa7 0x70 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe4 0x1 0xab 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0xac 0x6d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe5 0x0 0xad 0x60 0x0 0xcc 0xff 0x0 0x0 0x6 0xad 0xfb 0x2 0xcc 0xff 0x0 0x0
|
||||||
|
0xe6 0x1 0xaf 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0xb5 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe7 0x1 0xb6 0x70 0x0 0x0 0x0 0x0 0x0 0x1 0xb8 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe8 0x1 0xbd 0x70 0x0 0x0 0x0 0x0 0x0 0x1 0xc0 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe9 0x1 0xc2 0x68 0x0 0x0 0x0 0x0 0x0 0x1 0xc3 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xea 0x1 0xc4 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0xc7 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xeb 0x1 0xc8 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0xc9 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xec 0x1 0xcc 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0xcd 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xed 0x1 0xce 0x54 0x0 0x0 0x0 0x0 0x0 0x1 0xd1 0x4d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xee 0x1 0xd2 0x4c 0x0 0x0 0x0 0x0 0x0 0x1 0xd3 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xef 0x1 0xd8 0x49 0x0 0x0 0x0 0x0 0x0 0x1 0xda 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf0 0x1 0xdc 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0xdd 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf1 0x1 0xdf 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0xe0 0x52 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf2 0x1 0xe2 0x53 0x0 0x0 0x0 0x0 0x0 0x1 0xe4 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf3 0x1 0xe5 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0xe7 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf4 0x1 0xe9 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0xea 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf5 0x1 0xeb 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0xee 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf6 0x1 0xef 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0xf4 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf7 0x1 0xf5 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0xf8 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf8 0x1 0xfa 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0xff 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf9 0x1 0x1 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0x3 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfa 0x1 0x4 0x59 0x0 0x0 0x0 0x0 0x0 0x1 0x6 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfb 0x1 0x7 0x61 0x0 0x0 0x0 0x0 0x0 0x1 0x9 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfc 0x1 0xc 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0x10 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfd 0x1 0x11 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0x12 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xfe 0x1 0x15 0x70 0x0 0x0 0x0 0x0 0x0 0x1 0x16 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xff 0x1 0x17 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0x1c 0x6d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x0 0x1 0x1f 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x21 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1 0x1 0x25 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x26 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2 0x1 0x28 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0x2a 0x6f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3 0x1 0x2e 0x6e 0x0 0x0 0x0 0x0 0x0 0x1 0x30 0x6d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4 0x1 0x32 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x33 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5 0x1 0x34 0x69 0x0 0x0 0x0 0x0 0x0 0x1 0x38 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x6 0x1 0x39 0x67 0x0 0x0 0x0 0x0 0x0 0x1 0x3d 0x66 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x7 0x1 0x3e 0x67 0x0 0x0 0x0 0x0 0x0 0x1 0x41 0x6e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x8 0x1 0x42 0x6f 0x0 0x0 0x0 0x0 0x0 0x1 0x43 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x9 0x0 0x44 0x9f 0x2 0x56 0xfe 0x0 0x0 0x6 0x44 0x4 0x4 0x56 0xfe 0x0 0x0
|
||||||
|
0xa 0x0 0x45 0xfd 0xff 0x2 0x0 0x1 0x0 0x6 0x45 0x4 0x4 0x2 0x0 0x1 0x0
|
||||||
|
0xb 0x1 0x46 0x67 0x0 0x0 0x0 0x0 0x0 0x1 0x47 0x6c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xc 0x1 0x48 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x4a 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xd 0x1 0x4c 0x67 0x0 0x0 0x0 0x0 0x0 0x1 0x4d 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xe 0x1 0x4f 0x6b 0x0 0x0 0x0 0x0 0x0 0x1 0x50 0x6a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0xf 0x1 0x52 0x69 0x0 0x0 0x0 0x0 0x0 0x1 0x54 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x10 0x1 0x59 0x68 0x0 0x0 0x0 0x0 0x0 0x1 0x5a 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x11 0x1 0x5b 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x5e 0x65 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x12 0x1 0x5f 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0x64 0x63 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x13 0x1 0x68 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0x69 0x65 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x14 0x1 0x6e 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x6f 0x68 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x15 0x1 0x74 0x68 0x0 0x0 0x0 0x0 0x0 0x1 0x76 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x16 0x1 0x77 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x7c 0x65 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x17 0x1 0x7e 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x85 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x18 0x1 0x86 0x65 0x0 0x0 0x0 0x0 0x0 0x1 0x87 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x19 0x1 0x8a 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x8c 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1a 0x1 0x90 0x60 0x0 0x0 0x0 0x0 0x0 0x1 0x91 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1b 0x1 0x93 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x95 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1c 0x1 0x96 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x9b 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1d 0x1 0x9d 0x5f 0x0 0x0 0x0 0x0 0x0 0x1 0x9e 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1e 0x1 0xa0 0x65 0x0 0x0 0x0 0x0 0x0 0x1 0xa2 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x1f 0x1 0xa3 0x5d 0x0 0x0 0x0 0x0 0x0 0x1 0xa5 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x20 0x1 0xa7 0x52 0x0 0x0 0x0 0x0 0x0 0x1 0xa8 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x21 0x1 0xa9 0x4e 0x0 0x0 0x0 0x0 0x0 0x1 0xac 0x4d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x22 0x1 0xad 0x4c 0x0 0x0 0x0 0x0 0x0 0x1 0xae 0x4b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x23 0x1 0xb1 0x4a 0x0 0x0 0x0 0x0 0x0 0x1 0xb2 0x4c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x24 0x1 0xb3 0x4b 0x0 0x0 0x0 0x0 0x0 0x1 0xb6 0x4a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x25 0x1 0xb8 0x4b 0x0 0x0 0x0 0x0 0x0 0x1 0xba 0x4c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x26 0x1 0xbc 0x4d 0x0 0x0 0x0 0x0 0x0 0x1 0xbd 0x4e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x27 0x1 0xc1 0x50 0x0 0x0 0x0 0x0 0x0 0x1 0xc2 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x28 0x1 0xc4 0x52 0x0 0x0 0x0 0x0 0x0 0x1 0xc7 0x53 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x29 0x1 0xc9 0x54 0x0 0x0 0x0 0x0 0x0 0x1 0xce 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2a 0x1 0xcf 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0xd0 0x55 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2b 0x1 0xd3 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0xd4 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2c 0x1 0xd5 0x54 0x0 0x0 0x0 0x0 0x0 0x1 0xd8 0x53 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2d 0x1 0xd9 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0xdd 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2e 0x1 0xdf 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0xe1 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x2f 0x1 0xe3 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0xe6 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x30 0x1 0xe8 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0xe9 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x31 0x1 0xeb 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0xec 0x53 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x32 0x1 0xee 0x52 0x0 0x0 0x0 0x0 0x0 0x1 0xf0 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x33 0x1 0xf1 0x4a 0x0 0x0 0x0 0x0 0x0 0x1 0xf3 0x49 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x34 0x1 0xf5 0x42 0x0 0x0 0x0 0x0 0x0 0x1 0xf6 0x43 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x35 0x1 0xf7 0x44 0x0 0x0 0x0 0x0 0x0 0x1 0xfa 0x4b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x36 0x1 0xfb 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0xfc 0x50 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x37 0x1 0xff 0x4f 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x50 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x38 0x1 0x1 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0x5 0x50 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x39 0x1 0x8 0x53 0x0 0x0 0x0 0x0 0x0 0x1 0xa 0x51 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3a 0x1 0xf 0x51 0x0 0x0 0x0 0x0 0x0 0x1 0x12 0x53 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3b 0x1 0x13 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x15 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3c 0x1 0x17 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0x18 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3d 0x1 0x19 0x5f 0x0 0x0 0x0 0x0 0x0 0x1 0x1c 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3e 0x1 0x1e 0x5f 0x0 0x0 0x0 0x0 0x0 0x1 0x21 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x3f 0x1 0x22 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0x23 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x40 0x1 0x26 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x27 0x5f 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x41 0x1 0x2b 0x5e 0x0 0x0 0x0 0x0 0x0 0x1 0x2f 0x5d 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x42 0x1 0x31 0x5c 0x0 0x0 0x0 0x0 0x0 0x1 0x32 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x43 0x1 0x34 0x5b 0x0 0x0 0x0 0x0 0x0 0x1 0x35 0x5c 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x44 0x1 0x37 0x5d 0x0 0x0 0x0 0x0 0x0 0x1 0x39 0x5e 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x45 0x1 0x3a 0x5f 0x0 0x0 0x0 0x0 0x0 0x1 0x3b 0x61 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x46 0x1 0x3e 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x3f 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x47 0x1 0x43 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x44 0x64 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x48 0x1 0x45 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x47 0x62 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x49 0x1 0x49 0x61 0x0 0x0 0x0 0x0 0x0 0x1 0x4e 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4a 0x1 0x4f 0x61 0x0 0x0 0x0 0x0 0x0 0x1 0x51 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4b 0x1 0x52 0x61 0x0 0x0 0x0 0x0 0x0 0x1 0x56 0x62 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4c 0x1 0x57 0x63 0x0 0x0 0x0 0x0 0x0 0x1 0x58 0x62 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4d 0x1 0x5b 0x64 0x0 0x0 0x0 0x0 0x0 0x1 0x5d 0x65 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4e 0x1 0x60 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x62 0x67 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x4f 0x1 0x65 0x66 0x0 0x0 0x0 0x0 0x0 0x1 0x66 0x60 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x50 0x1 0x67 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x69 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x51 0x1 0x6b 0x50 0x0 0x0 0x0 0x0 0x0 0x1 0x6c 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x52 0x1 0x6e 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0x71 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x53 0x1 0x73 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0x74 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x54 0x1 0x78 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x7d 0x5a 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x55 0x1 0x82 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x83 0x5b 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x56 0x1 0x87 0x5a 0x0 0x0 0x0 0x0 0x0 0x1 0x88 0x59 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x57 0x1 0x8b 0x58 0x0 0x0 0x0 0x0 0x0 0x1 0x8d 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x58 0x1 0x8e 0x56 0x0 0x0 0x0 0x0 0x0 0x1 0x90 0x57 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x59 0x1 0x93 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0x96 0x54 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5a 0x1 0x98 0x55 0x0 0x0 0x0 0x0 0x0 0x1 0x9c 0x56 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5b 0x1 0x9f 0x57 0x0 0x0 0x0 0x0 0x0 0x1 0xa0 0x58 0x0 0x0 0x0 0x0 0x0
|
||||||
|
0x5c 0x1 0xa4 0x59 0x0 0x0 0x0 0x0 0x0 0x2 0xa8 0x0 0x0 0x0 0x0 0x0 0x0
|
Loading…
Reference in New Issue
Block a user