Skip to content

Commit

Permalink
Merge pull request #11 from GeoTecINIT/plugin-preps
Browse files Browse the repository at this point in the history
Plugin preps
  • Loading branch information
matey97 authored Jul 25, 2022
2 parents c590339 + f02b287 commit a60df8d
Show file tree
Hide file tree
Showing 124 changed files with 2,062 additions and 1,686 deletions.
6 changes: 2 additions & 4 deletions demo/app/app.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Application } from "@nativescript/core";
import { wearosSensors } from "nativescript-wearos-sensors/wearos-sensors.android";
import { appTasks } from "~/home/tasks";
import { demoTaskGraph } from "~/home/tasks/graph";
import { wearosSensors } from "nativescript-wearos-sensors";

wearosSensors.init(appTasks, demoTaskGraph);
wearosSensors.init();

Application.run({ moduleName: "app-root" });

Expand Down
50 changes: 31 additions & 19 deletions demo/app/home/device-list/device-list-view-model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Observable } from "@nativescript/core";
import { getLogger } from "~/home/logger/logger-view-model";
import { getNodeDiscoverer, NodeDiscovered } from "nativescript-wearos-sensors/node";
import { getNodeDiscoverer } from "nativescript-wearos-sensors/node";
import { getFreeMessageClient } from "nativescript-wearos-sensors/internal/communication/free-message";
import { getCollectorManager } from "nativescript-wearos-sensors/internal/collection";
import { getStore } from "~/home/store";

export class DeviceListViewModel extends Observable {

Expand All @@ -13,6 +16,16 @@ export class DeviceListViewModel extends Observable {
this.logger = getLogger();
this.scanning = false;
this.nodes = [];

getCollectorManager().addSensorListener((sensorRecord) => {
const samples = sensorRecord.samples;
const deviceId = sensorRecord.deviceId;
getStore().addRecord(sensorRecord);
this.logger.logResultForNode(deviceId, JSON.stringify(samples));
});
getFreeMessageClient().registerListener((receivedMessage) => {
this.logger.logInfo(`received single message ${JSON.stringify(receivedMessage)}`);
});
}

getNode(index: number): ConnectedNode {
Expand All @@ -29,32 +42,31 @@ export class DeviceListViewModel extends Observable {
this.notifyPropertyChange("nodes", this.nodes);
this.notifyPropertyChange("scanning", this.scanning);

nodeDiscoverer.getConnectedNodes().subscribe({
next: (nodeDiscovered: NodeDiscovered) => {
if (nodeDiscovered.error) {
this.logger.logResult(nodeDiscovered.error);
return;
}
nodeDiscoverer.getConnectedNodes()
.then((nodesDiscovered) => {
nodesDiscovered.forEach((nodeDiscovered) => {
if (nodeDiscovered.error) {
this.logger.logResult(nodeDiscovered.error);
return;
}

const node = nodeDiscovered.node;
this.logger.logResult(`Connected node --> ${JSON.stringify(node)}`);
const node = nodeDiscovered.node;
this.logger.logResult(`Connected node --> ${JSON.stringify(node)}`);

const sensorsAvailability = {};
node.capabilities.forEach((capability) => sensorsAvailability[capability.toLowerCase()] = true)
const sensorsAvailability = {};
node.capabilities.forEach((capability) => sensorsAvailability[capability.toLowerCase()] = true)

this.nodes.push({
id: node.id,
name: node.name,
sensorsAvailability: sensorsAvailability,
this.nodes.push({
id: node.id,
name: node.name,
sensorsAvailability: sensorsAvailability,
});
});
this.notifyPropertyChange("nodes", this.nodes);
},
complete: () => {
this.logger.logInfo("Scan ended");
this.scanning = false;
this.notifyPropertyChange("scanning", this.scanning);
}
});
});
}
}

Expand Down
48 changes: 32 additions & 16 deletions demo/app/home/device/device-page.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,62 @@
<ActionBar>
<Label class="title-med">
<FormattedString>
<Span text="{{ node.name }} " fontWeight="bold"></Span>
<Span text="{{ ' (' + node.id + ')' }}"></Span>
<Span text="{{ node.name }} " fontWeight="bold"/>
<Span text="{{ ' (' + node.id + ')' }}"/>
</FormattedString>
</Label>
<ActionItem
text="Store collected data"
tap="{{ onStoreData }}"
android.position="popup"
></ActionItem>
/>
<ActionItem
text="Clear collected data"
tap="{{ onClearData }}"
android.position="popup"
></ActionItem>
/>
</ActionBar>

<StackLayout orientation="vertical">
<GridLayout class="card" rows="auto, auto" columns="*, *" height="80">
<Label row="0" col="0" text="Sensor Delay: "></Label>
<dd:DropDown row="1" col="0"
items="{{ sensorDelays }}" selectedIndex="{{ selectedDelayIndex }}"
itemsTextAlignment="center" itemsPadding="5" class="drop-down"/>
<Label row="0" col="1" text="Batch size: "></Label>
<TextField row="1" col="1" text="{{ batchSize }}" keyboardType="number" textAlignment="center"></TextField>
<GridLayout rows="auto, auto" columns="*, *" class="card" height="100">
<Label row="0" col="0" colspan="2" class="bold" text="FreeMessages"/>
<Button row="1" col="0"
backgroundColor="deepskyblue"
tap="{{ onTestFreeMessage }}"
text="Single"/>
<Button row="1" col="1"
backgroundColor="deepskyblue"
tap="{{ onTestFreeMessageWithResponse }}"
text="Single with response"/>
</GridLayout>
<GridLayout class="card" rows="auto, auto" columns="2*, *" height="80">
<Label row="0" col="0" class="bold" text="Sensor interval: "/>
<StackLayout row="1" col="0" orientation="horizontal">
<dd:DropDown items="{{ sensorIntervals }}" selectedIndex="{{ selectedDelayIndex }}"
itemsTextAlignment="center" itemsPadding="5" class="drop-down"/>
<Label text="or" verticalAlignment="center"/>
<TextField text="{{ customSensorInterval }}" hint="custom" style="placeholder-color: grey;"
keyboardType="number" textAlignment="center" width="50"/>
<Label text="ms" verticalAlignment="center"/>
</StackLayout>
<Label row="0" col="1" class="bold" text="Batch size: "/>
<TextField row="1" col="1" text="{{ batchSize }}" keyboardType="number" textAlignment="center"/>
</GridLayout>
<ScrollView verticalAlignment="top">
<Repeater id="repeater" items="{{ sensorDescription }}" margin="10">
<Repeater.itemsLayout>
<StackLayout orientation="vertical"></StackLayout>
<StackLayout orientation="vertical"/>
</Repeater.itemsLayout>
<Repeater.itemTemplate>
<GridLayout rows="auto, auto, *" columns="1*, 3*" class="card">
<Label row="0" rowSpan="3" col="0" text="{{ $value.icon }}"
class="{{ $value.status.id, $value.status.id === 'listening' ? 'mdi-ro mdi-50 recording' : 'mdi-ro mdi-50'}}"
backgroundColor="{{ $value.status.iconColorBg }}" horizontalAlignment="center" verticalAlignment="center"></Label>
<Label row="0" col="1" text="{{ $value.sensor }}" class="title-med bold"></Label>
backgroundColor="{{ $value.status.iconColorBg }}" horizontalAlignment="center" verticalAlignment="center"/>
<Label row="0" col="1" text="{{ $value.sensor }}" class="title-med bold"/>
<Label row="1" col="1" class="bold">
<FormattedString>
<Span text="Status: "></Span>
<Span text="{{ $value.status.message }}"></Span>
<Span text="Status: "/>
<Span text="{{ $value.status.message }}"/>
</FormattedString>
</Label>
<StackLayout row="3" col="1" orientation="horizontal" horizontalAlignment="center">
Expand Down
130 changes: 76 additions & 54 deletions demo/app/home/device/device-view-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { Button, Color, EventData, Observable, Repeater } from "@nativescript/co
import { getLogger } from "~/home/logger/logger-view-model";
import { ValueList } from "nativescript-drop-down";
import { Node } from "nativescript-wearos-sensors/node";
import { CollectorManager, PrepareError, SensorDelay } from "nativescript-wearos-sensors/collection";
import { getSensorCollector, SensorType } from "nativescript-wearos-sensors/sensors";
import { wearosSensors } from "nativescript-wearos-sensors";
import { pascalCase } from "nativescript-wearos-sensors/internal/utils/strings";
import { getCollectorManager, PrepareError, NativeSensorDelay } from "nativescript-wearos-sensors/collection";
import { SensorType } from "nativescript-wearos-sensors/sensors";
import { getStore } from "~/home/store";
import { getFreeMessageClient, FreeMessageClient } from "nativescript-wearos-sensors/free-message";


export class DeviceViewModel extends Observable {
private logger;
Expand All @@ -29,16 +30,19 @@ export class DeviceViewModel extends Observable {

private repeater: Repeater;

private sensorDelays = new ValueList([
{ value: SensorDelay.NORMAL, display: "NORMAL" },
{ value: SensorDelay.UI, display: "UI" },
{ value: SensorDelay.GAME, display: "GAME" },
{ value: SensorDelay.FASTEST, display: "FASTEST" }
private customSensorInterval: number;
private sensorIntervals = new ValueList([
{ value: NativeSensorDelay.NORMAL, display: "NORMAL" },
{ value: NativeSensorDelay.UI, display: "UI" },
{ value: NativeSensorDelay.GAME, display: "GAME" },
{ value: NativeSensorDelay.FASTEST, display: "FASTEST" }
]);
private selectedDelayIndex = 0;

private batchSize = 50;

private freeMessageClient: FreeMessageClient;

constructor(
private node: Node
) {
Expand All @@ -47,16 +51,39 @@ export class DeviceViewModel extends Observable {
this.sensorDescription = this.node.capabilities.map((sensor) => {
return {
parent: this,
collector: getSensorCollector(sensor),
sensor: sensor,
status: {
id: Status.AVAILABLE_IN_DEVICE,
message: this.status["availableInDevice"],
iconColorBg: this.bgColors["availableInDevice"]
},
icon: this.iconForSensor(sensor),
icon: iconForSensor(sensor),
};
});

this.freeMessageClient = getFreeMessageClient();
}

async onTestFreeMessage() {
if (!this.freeMessageClient.enabled()) {
this.logger.logInfo(`Free messages are not enabled`);
return;
}
const freeMessage = { message: "You don't have to reply :)"};
this.logger.logInfoForNode(this.node.name, `sending ${JSON.stringify(freeMessage)}`);
await this.freeMessageClient.send(this.node, freeMessage);
}

async onTestFreeMessageWithResponse() {
if (!this.freeMessageClient.enabled()) {
this.logger.logInfo(`Free messages are not enabled`);
return;
}

const freeMessage = { message: "PING!"};
this.logger.logInfoForNode(this.node.name, `sending ${JSON.stringify(freeMessage)} and awaiting for response`);
const receivedMessage = await this.freeMessageClient.sendExpectingResponse(this.node, freeMessage);
this.logger.logResultForNode(this.node.name, `response received: ${JSON.stringify(receivedMessage)}`);
}

setRepeater(repeater) {
Expand Down Expand Up @@ -91,21 +118,22 @@ export class DeviceViewModel extends Observable {
parent.handleOnStopTap(sensorDescription);
}

onStoreData() {
wearosSensors.emitEvent("storeCollectedData", {
deviceId: this.node.id
});
async onStoreData() {
const fileName = `${this.node.id}_${Date.now()}.json`
await getStore().store(fileName);
this.logger.logInfo(`collected data has been stored in internal memory as ${fileName}`);
}

onClearData() {
wearosSensors.emitEvent("clearCollectedData");
getStore().clear();
this.logger.logInfo("collected data has been deleted");
}

private handleOnIsReadyTap(sensorDescription: SensorDescription) {
this.updateSensorDescriptionStatus(sensorDescription, Status.WAITING_FOR_RESPONSE);

this.logger.logInfoForNode(this.node.name, `Sending isReady request and waiting for response...`);
sensorDescription.collector.isReady(this.node).then((ready) => {
getCollectorManager().isReady(this.node, sensorDescription.sensor).then((ready) => {
this.logger.logResultForNode(this.node.name, `Ready response: ${ ready ? 'node ready' : 'node not ready. Should prepare node'}`);
let status;
if (ready) {
Expand All @@ -122,7 +150,7 @@ export class DeviceViewModel extends Observable {
this.updateSensorDescriptionStatus(sensorDescription, Status.WAITING_FOR_RESPONSE)

this.logger.logInfoForNode(this.node.name, `Sending prepare request to node and waiting for response. Should look at wearable device...`);
sensorDescription.collector.prepare(this.node).then((prepareError: PrepareError) => {
getCollectorManager().prepare(this.node, sensorDescription.sensor).then((prepareError: PrepareError) => {
this.logger.logResultForNode(this.node.name, `Prepare response: ${ prepareError ? prepareError.message : 'device prepared successfully'}`);
let status;
if (prepareError) {
Expand All @@ -137,26 +165,21 @@ export class DeviceViewModel extends Observable {
}

private handleOnStartTap(sensorDescription: SensorDescription) {
wearosSensors.emitEvent(
`start${pascalCase(sensorDescription.sensor)}Command`,
getCollectorManager().startCollecting(
this.node,
sensorDescription.sensor,
{
deviceId: this.node.id,
config: {
sensorDelay: this.sensorDelays.getValue(this.selectedDelayIndex),
batchSize: this.batchSize
}
sensorInterval: this.customSensorInterval ?? this.sensorIntervals.getValue(this.selectedDelayIndex),
batchSize: this.batchSize
}
);

this.updateSensorDescriptionStatus(sensorDescription, Status.LISTENING);
}

private handleOnStopTap(sensorDescription: SensorDescription) {
wearosSensors.emitEvent(
`stop${pascalCase(sensorDescription.sensor)}Command`,
{
deviceId: this.node.id
}
);
getCollectorManager().stopCollecting(this.node, sensorDescription.sensor);

this.updateSensorDescriptionStatus(sensorDescription, Status.READY);
}

Expand All @@ -169,33 +192,10 @@ export class DeviceViewModel extends Observable {
}
this.repeater.refresh();
}

private iconForSensor(sensor): string {
let icon;
switch (sensor) {
case SensorType.ACCELEROMETER:
icon = "e89f";
break;
case SensorType.GYROSCOPE:
icon = "e84d";
break;
case SensorType.MAGNETOMETER:
icon = "e87a";
break;
case SensorType.LOCATION:
icon = "e0c8";
break;
case SensorType.HEART_RATE:
icon = "e87d";
}

return String.fromCharCode(parseInt(icon, 16));
}
}

interface SensorDescription {
parent: DeviceViewModel,
collector: CollectorManager,
sensor: SensorType,
status: SensorStatus,
icon: string,
Expand All @@ -214,3 +214,25 @@ enum Status {
READY = "ready",
LISTENING = "listening"
}

function iconForSensor(sensor: SensorType): string {
let icon;
switch (sensor) {
case SensorType.ACCELEROMETER:
icon = "e89f";
break;
case SensorType.GYROSCOPE:
icon = "e84d";
break;
case SensorType.MAGNETOMETER:
icon = "e87a";
break;
case SensorType.LOCATION:
icon = "e0c8";
break;
case SensorType.HEART_RATE:
icon = "e87d";
}

return String.fromCharCode(parseInt(icon, 16));
}
Loading

0 comments on commit a60df8d

Please sign in to comment.