Skip to content

Commit

Permalink
ShowUntracked checkbox (#755)
Browse files Browse the repository at this point in the history
  • Loading branch information
DTTerastar authored Sep 30, 2024
1 parent 8be0b52 commit ce81b87
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 63 deletions.
10 changes: 5 additions & 5 deletions agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

export WORKSPACE_BASE=$(pwd)

sudo docker run \
-it \
--pull=always \
--add-host host.docker.internal:host-gateway \
docker pull ghcr.io/all-hands-ai/runtime:0.9-nikolaik

docker run -it --pull=always \
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.9-nikolaik \
-e SANDBOX_USER_ID=$(id -u) \
-e LLM_OLLAMA_BASE_URL="http://host.docker.internal:11434" \
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
-v $WORKSPACE_BASE:/opt/workspace_base \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands-app-$(date +%Y%m%d%H%M%S) \
ghcr.io/all-hands-ai/openhands:0.9
14 changes: 10 additions & 4 deletions src/Controllers/StateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ public IEnumerable<NodeState> GetNodes(bool includeTele = true)

// GET: api/rooms
[HttpGet("api/state/devices")]
public IEnumerable<Device> GetDevices()
public IEnumerable<Device> GetDevices([FromQuery] bool showUntracked = false)
{
return _state.Devices.Values.Where(a => a is { Track: true });
IEnumerable<Device> d = _state.Devices.Values;
if (!showUntracked) d = d.Where(a => a is { Track: true });
return d;
}

// GET: api/config
Expand Down Expand Up @@ -81,7 +83,7 @@ public Calibration GetCalibration()

[ApiExplorerSettings(IgnoreApi = true)]
[Route("/ws")]
public async Task Get()
public async Task Get([FromQuery] bool showUntracked = false)
{
if (!HttpContext.WebSockets.IsWebSocketRequest)
{
Expand All @@ -99,7 +101,11 @@ void EnqueueAndSignal<T>(T value)
void OnConfigChanged(object? sender, Config e) => EnqueueAndSignal(new { type = "configChanged" });
void OnCalibrationChanged(object? sender, CalibrationEventArgs e) => EnqueueAndSignal(new { type = "calibrationChanged", data = e.Calibration });
void OnNodeStateChanged(object? sender, NodeStateEventArgs e) => EnqueueAndSignal(new { type = "nodeStateChanged", data = e.NodeState });
void OnDeviceChanged(object? sender, DeviceEventArgs e) => EnqueueAndSignal(new { type = "deviceChanged", data = e.Device });
void OnDeviceChanged(object? sender, DeviceEventArgs e)
{
if (showUntracked || (e.Device?.Track ?? false) || e.TrackChanged)
EnqueueAndSignal(new { type = "deviceChanged", data = e.Device });
};

_config.ConfigChanged += OnConfigChanged;
_eventDispatcher.CalibrationChanged += OnCalibrationChanged;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public void OnNodeStateChanged(NodeState state)
NodeStateChanged?.Invoke(this, new NodeStateEventArgs(state));
}

public void OnDeviceChanged(Device device)
public void OnDeviceChanged(Device device, bool trackChanged)
{
DeviceStateChanged?.Invoke(this, new DeviceEventArgs(device));
DeviceStateChanged?.Invoke(this, new DeviceEventArgs(device, trackChanged));
}

public void OnCalibrationChanged(Calibration calibration)
Expand All @@ -29,9 +29,10 @@ public class NodeStateEventArgs(NodeState state) : EventArgs
public NodeState NodeState { get; } = state;
}

public class DeviceEventArgs(Device device) : EventArgs
public class DeviceEventArgs(Device device, bool trackChanged) : EventArgs
{
public Device Device { get; } = device;
public bool TrackChanged { get; } = trackChanged;
}

public class CalibrationEventArgs(Calibration calibration) : EventArgs
Expand Down
10 changes: 6 additions & 4 deletions src/Models/Device.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Text;
using System.Text.Json.Serialization;
using ESPresense.Converters;
using MathNet.Spatial.Euclidean;
Expand All @@ -16,10 +17,11 @@ public Device(string id, string? discoveryId, TimeSpan timeout)

public override string ToString()
{
if (Track)
return $"{nameof(Id)}: {Id}";
else
return $"Untracked {nameof(Id)}: {Id}";
StringBuilder sb = new();
sb.Append($"{nameof(Id)}: {Id}");
if (!string.IsNullOrEmpty(Name)) sb.Append($", {nameof(Name)}: {Name}");
if (!Track) sb.Append($", {nameof(Track)}: {Track}");
return sb.ToString();
}

public string Id { get; init; }
Expand Down
11 changes: 8 additions & 3 deletions src/Services/DeviceTracker.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Threading.Channels;
using ESPresense.Controllers;
using ESPresense.Models;
using Serilog;

namespace ESPresense.Services;

public class DeviceTracker(State state, MqttCoordinator mqtt, TelemetryService tele) : BackgroundService
public class DeviceTracker(State state, MqttCoordinator mqtt, TelemetryService tele, GlobalEventDispatcher globalEventDispatcher) : BackgroundService
{
private readonly Channel<Device> _toProcessChannel = Channel.CreateUnbounded<Device>();
private readonly Channel<Device> _toLocateChannel = Channel.CreateUnbounded<Device>();
Expand Down Expand Up @@ -91,9 +92,11 @@ private async Task ProcessDevicesAsync(CancellationToken stoppingToken)
await foreach (var device in _toProcessChannel.Reader.ReadAllAsync(stoppingToken))
{
if (stoppingToken.IsCancellationRequested) break;
await CheckDeviceAsync(device);
var trackChanged = await CheckDeviceAsync(device);
if (device.Track)
await _toLocateChannel.Writer.WriteAsync(device, stoppingToken);
else
globalEventDispatcher.OnDeviceChanged(device, trackChanged);
}
}

Expand Down Expand Up @@ -131,7 +134,7 @@ private bool ShouldTrackDevice(Device device)
return false;
}

private async Task CheckDeviceAsync(Device device)
private async Task<bool> CheckDeviceAsync(Device device)
{
var wasTracked = device.Track;
if (device.Check)
Expand All @@ -155,7 +158,9 @@ private async Task CheckDeviceAsync(Device device)
foreach (var ad in device.HassAutoDiscovery)
await ad.Delete(mqtt);
}
return true;
}
return false;
}

public IAsyncEnumerable<Device> GetConsumingEnumerable(CancellationToken cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion src/Services/MultiScenarioLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ await mqtt.EnqueueAsync($"espresense/companion/{device.Id}/attributes",
}, SerializerSettings.NullIgnore)
);

globalEventDispatcher.OnDeviceChanged(device);
globalEventDispatcher.OnDeviceChanged(device, false);
if (state?.Config?.History?.Enabled ?? false)
{
foreach (var ds in device.Scenarios.Where(ds => ds.Confidence != 0))
Expand Down
98 changes: 56 additions & 42 deletions src/ui/src/lib/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,54 +43,68 @@ async function getConfig() {

getConfig();

export const devices = readable<Device[]>([], function start(set) {
let deviceMap = new Map();
export const showUntracked = writable<boolean>(false);

export const devices = derived<[typeof showUntracked], Device[]>(
[showUntracked],
([$showUntracked], set) => {
let deviceMap = new Map();
var q = (new URLSearchParams({
showUntracked: $showUntracked ? "true" : "false"
})).toString();

function updateDevicesFromMap() {
const devicesArray = Array.from(deviceMap.values());
set(devicesArray);
}

function fetchDevices() {

fetch(`${base}/api/state/devices?${q}`)
.then((d) => d.json())
.then((r) => {
deviceMap = new Map(r.map((device: Device) => [device.id, device]));
updateDevicesFromMap();
})
.catch((ex) => {
console.error('Error fetching devices:', ex);
});
}

function updateDevicesFromMap() {
var a = Array.from(deviceMap.values());
set(a);
}
fetchDevices();

function fetchDevices() {
fetch(`${base}/api/state/devices`)
.then((d) => d.json())
.then((r) => {
deviceMap = new Map(r.map((device) => [device.id, device]));
updateDevicesFromMap();
})
.catch((ex) => {
console.log(ex);
const interval = setInterval(fetchDevices, 60000);

function setupWebsocket() {
const loc = new URL(`${base}/ws?${q}`, window.location.href);
const new_uri = (loc.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + loc.host + loc.pathname + loc.search;
const socket = new WebSocket(new_uri);

socket.addEventListener('message', async function (event) {
const eventData = JSON.parse(event.data);
if (eventData.type === 'deviceChanged' && eventData.data?.id) {
deviceMap.set(eventData.data.id, eventData.data);
updateDevicesFromMap();
} else if (eventData.type === 'configChanged') {
getConfig();
} else if (eventData.type === 'time') {
relative.set(eventData.data);
} else {
console.log('Unhandled websocket event:', event.data);
}
});
}

fetchDevices();
return socket;
}

const interval = setInterval(() => {
fetchDevices();
}, 60000);

function setupWebsocket() {
var loc = new URL(`${base}/ws`, window.location.href);
var new_uri = (loc.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + loc.host + loc.pathname;
socket = new WebSocket(new_uri);
socket.addEventListener('message', async function (event) {
var eventData = JSON.parse(event.data);
if (eventData.type === 'deviceChanged' && eventData.data?.id) {
deviceMap.set(eventData.data.id, eventData.data);
updateDevicesFromMap();
} else if (eventData.type == 'configChanged') {
getConfig();
} else if (eventData.type == 'time') relative.set(eventData.data);
else console.log(event.data);
});
}
const socket = setupWebsocket();

setupWebsocket();

return function stop() {
clearInterval(interval);
};
});
return () => {
clearInterval(interval);
socket.close();
};
}
);

export const nodes = readable<Node[]>([], function start(set) {
var errors = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/ui/src/routes/devices/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts">
import DevicesTable from '$lib/DevicesTable.svelte';
import { detail } from '$lib/urls';
import { SlideToggle } from '@skeletonlabs/skeleton';
import { showUntracked } from '$lib/stores';
</script>

<svelte:head>
Expand All @@ -9,5 +11,8 @@

<div class="container mx-auto p-2">
<h1 class="text-3xl font-bold my-2 px-2">Devices</h1>
<div class="flex items-center mb-4">
<SlideToggle name="show-untracked" bind:checked={$showUntracked}>Show Untracked</SlideToggle>
</div>
<DevicesTable on:selected={(d) => detail(d.detail)} />
</div>
3 changes: 2 additions & 1 deletion tests/DeviceTrackerTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using ESPresense.Controllers;
using ESPresense.Locators;
using ESPresense.Models;
using ESPresense.Services;
Expand Down Expand Up @@ -29,7 +30,7 @@ public void TestMultiScenarioLocator()
{
var configLoader = new ConfigLoader("config");
var mqtt = new MqttCoordinator(configLoader, null, null);
var locator = new DeviceTracker(new State(configLoader), mqtt, new TelemetryService(mqtt));
var locator = new DeviceTracker(new State(configLoader), mqtt, new TelemetryService(mqtt), new GlobalEventDispatcher());
// Use testData to test locator...
// Assert.That(result, Is.EqualTo(expectedResult));
}
Expand Down

0 comments on commit ce81b87

Please sign in to comment.