An ESP32 based presence detection node for use with the Home Assistant mqtt_room
component or ESPresense-companion for indoor positioning
Documentation: https://espresense.com/
Building: building.
Release Notes: changelog.
HA Add-on / Docker container that solves indoor positions with mqtt data received from multiple ESPresense stations
License: Apache License 2.0
An ESP32 based presence detection node for use with the Home Assistant mqtt_room
component or ESPresense-companion for indoor positioning
Documentation: https://espresense.com/
Building: building.
Release Notes: changelog.
Hi! Super cool someone finally is creating a trilateration tool for ESPresense!
I got no idea how to code this but I got an idea I wanted to share:
As nodes can see each other it should already be possible to optimize detection based on measurements. I think this is what you're likely working on.
I thought to get one step further:
What about placing an iBeacon or Eddystone at a specific location and enter the actual distances to the nodes - or better: placing it visually on the floormap.
The system could then calculate the calibration values out of the actual measurements per node.
This could be done multiple times from different locations to improve the measurements and calibration.
Updated to 0.3.31 and all sections of the WebUI are badly broken. No icon graphics loading (just the camera icon indicating broken links), text checkboxes, and the map display is just totally wonky, with the rooms in color toward the bottom, black ellipses at the top, and the stats displayed as plain text below the rooms.
Tried uninstalling and reinstalling, but got the same results. Running HAOS in a ProxMox VM on a Beelink S12 N95 NUC-style box.
I greatly appreciate all the work that's gone into both the core app and Companion. This is a really neat system that has a ton of potential. That said, I have a somewhat lower priority feature request. Hopefully this is the right place to submit those.
Now that I finally have my system setup and running, I think it would be nice to see an option to reduce or increase the logging level in the Companion to help with calibration/troubleshooting vs. normal operation. Right now my log looks like this:
[10:00:12 INF] HTTP GET /api/state/calibration responded 200 in 1.5912 ms
[10:00:13 INF] HTTP GET /api/state/calibration responded 200 in 0.9463 ms
[10:00:14 INF] HTTP GET /api/state/calibration responded 200 in 0.8854 ms
[10:00:15 INF] HTTP GET /api/state/calibration responded 200 in 0.9576 ms
[10:00:16 INF] HTTP GET /api/state/calibration responded 200 in 0.9325 ms
[10:00:16 INF] HTTP GET /_app/version.json responded 200 in 0.3717 ms
[10:00:17 INF] HTTP GET /api/state/calibration responded 200 in 0.9604 ms
[10:00:18 INF] HTTP GET /api/state/calibration responded 200 in 1.1026 ms
[10:00:19 INF] HTTP GET /api/state/calibration responded 200 in 0.9236 ms
[10:00:20 INF] HTTP GET /api/state/calibration responded 200 in 2.2351 ms
[10:00:21 INF] HTTP GET /api/state/calibration responded 200 in 0.9437 ms
[10:00:22 INF] HTTP GET /_app/version.json responded 200 in 0.4430 ms
[10:00:22 INF] HTTP GET /api/state/calibration responded 200 in 1.1701 ms
[10:00:24 INF] HTTP GET /api/state/calibration responded 200 in 14.3125 ms
[10:00:24 INF] HTTP GET /api/state/calibration responded 200 in 1.0162 ms
[10:00:42 INF] HTTP GET /_app/version.json responded 200 in 0.3343 ms
[10:00:42 INF] HTTP GET /api/state/calibration responded 200 in 3.4593 ms
[10:01:42 INF] HTTP GET /api/state/calibration responded 200 in 0.9559 ms
But I would like to see an option to only show calibration runs like this:
[10:19:11 INF] Optimizer Rx Adj Rssi found better results, rms 11.211<13.086
[10:19:11 INF] Optimizer set spare_office to Absorption: 3.25 RxAdj: 18 Error: 14.32864436929275
[10:19:11 INF] Optimizer set bedroom to Absorption: 3.25 RxAdj: 20 Error: 6.864019767155424
[10:19:11 INF] Optimizer set living_room to Absorption: 3.25 RxAdj: 20 Error: 9.422625777003502
[10:19:11 INF] Optimizer set redact_s_office to Absorption: 3.25 RxAdj: 03 Error: 15.872049594981899
[10:19:11 INF] Optimizer set basement_living_room to Absorption: 3.25 RxAdj: 08 Error: 11.536590187448445
[10:19:11 INF] Optimizer set redact2_s_office to Absorption: 3.25 RxAdj: 07 Error: 3.943304437023126
[10:19:11 INF] Optimizer Absorption Avg found better results, rms 6.618<11.211
[10:19:11 INF] Optimizer set spare_office to Absorption: 1.50 RxAdj: null Error: null
[10:19:11 INF] Optimizer set bedroom to Absorption: 2.27 RxAdj: null Error: null
[10:19:11 INF] Optimizer set living_room to Absorption: 2.23 RxAdj: null Error: null
[10:19:11 INF] Optimizer set redact_s_office to Absorption: 1.94 RxAdj: null Error: null
[10:19:11 INF] Optimizer set basement_living_room to Absorption: 2.48 RxAdj: null Error: null
[10:19:11 INF] Optimizer set redact2_s_office to Absorption: 2.71 RxAdj: null Error: null
[10:19:11 INF] Optimizer Absorption NelderMead found worse results, rms 9.334>6.618
Maybe even a further reduction to errors only as an option once I'm happy with the calibration.
Thanks again for all the hard work on this.
Edit: Wait, I'm an idiot. I see it's in there. I'm a bit confused though. Does Companion set its log level from MQTT? I must be missing something here.
Here is the stack trace - not sure it'f the infinity is legit and it's a json issue or if the root cause is it shouldn't be returning infinity ...
[21:10:12 ERR] Connection id "0HMT4AUVL3RG6", Request id "0HMT4AUVL3RG6:00000001": An unhandled exception was thrown by the application.
System.ArgumentException: .NET number values such as positive and negative infinity cannot be written as valid JSON. To make it work when using 'JsonSerializer', consider specifying 'JsonNumberHandling.AllowNamedFloatingPointLiterals' (see https://docs.microsoft.com/dotnet/api/system.text.json.serialization.jsonnumberhandling).
at System.Text.Json.ThrowHelper.ThrowArgumentException_ValueNotSupported()
at System.Text.Json.Utf8JsonWriter.WriteNumberValue(Double value)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3.OnWriteResume(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryWrite(Utf8JsonWriter writer, TDictionary dictionary, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3.OnWriteResume(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryWrite(Utf8JsonWriter writer, TDictionary dictionary, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3.OnWriteResume(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonDictionaryConverter`3.OnTryWrite(Utf8JsonWriter writer, TDictionary dictionary, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteCore[TValue](Utf8JsonWriter writer, TValue& value, JsonTypeInfo jsonTypeInfo, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
WORKS....
# Devices to track
devices:
- id: "node:*"`
CRASHES....
# Devices to track
devices:
- name: "*"
- id: "node:*"`
LOG
[23:13:34 INF] Now listening on: http://[::]:8267
[23:13:34 INF] Application started. Press Ctrl+C to shut down.
[23:13:34 INF] Hosting environment: Production
[23:13:34 INF] Content root path: /App
[23:13:35 ERR] BackgroundService failed
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.<InsertAsync>b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_0`1.<WriteAsync>b__0()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 46
at ESPresense.Controllers.GlobalEventDispatcher.OnDeviceChanged(Device device) in /App/src/Controllers/GlobalEventDispatcher.cs:line 21
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 76
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[23:13:35 FTL] The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost. A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping. To avoid this behavior, configure this to Ignore; however the BackgroundService will not be restarted.
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.<InsertAsync>b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_0`1.<WriteAsync>b__0()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 46
at ESPresense.Controllers.GlobalEventDispatcher.OnDeviceChanged(Device device) in /App/src/Controllers/GlobalEventDispatcher.cs:line 21
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 76
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[23:13:35 INF] Application is shutting down...
PLEASE HELP...
Thanks for your work! Just trying out the WIP. Is it my configuration problem or is a bigger problem?
I do not get to see any devices on devices list. I tried with wildcard and by specifying ID-s. Device is being tracked nicely by Home Assistant mqtt_room sensor when I configure by ID. On MQTT companion is online. Also I see devices updating on MQTT espresense/devices/#
I have the following config.
# MQTT Connection, if empty will query and use hassio provided mqtt
mqtt:
# How long before device considered stale
timeout: 30
# How long before device is considered away
away_timeout: 120
# Floors w/ the points to draw it in meters
floors:
- id: first
name: First Floor
# Bounds (x,y,z) of map in meters
bounds: [[-20, -20, -20], [20, 20,20]]
rooms:
- name: Labor
points:
- [0, 0]
- [13.983, 0]
- [13.983, 4.974]
- [0,4.974]
# Locations of espresense nodes in meters
nodes:
- name: pre2
point: [13.983, 4.974, 2.6]
floors: ["first"]
- name: pre1
point: [0, 4.974, 2.6]
floors: ["first"]
- name: pre3
point: [13.983, 0, 2.2]
floors: ["first"]
# Devices to track
devices:
- id: "*"
- id: "f6affb4f354f"
name: "Beacon1"
Log:
[14:47:20 INF] Loading /config/espresense/config.yaml
[14:47:22 WRN] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
[14:47:22 INF] Executing Query: pragma table_info("DeviceHistory")
[14:47:22 INF] Executing: create index if not exists "IX_DeviceHistory_When" on "DeviceHistory"("When")
[14:47:22 INF] Executing: DROP TRIGGER IF EXISTS DeviceHistory_RollingData;
[14:47:22 INF] Executing: CREATE TRIGGER DeviceHistory_RollingData AFTER INSERT ON DeviceHistory
BEGIN
DELETE FROM DeviceHistory WHERE `When` <= (NEW.`When`-1296000000000);
END;
[14:47:22 WRN] No XML encryptor configured. Key {3c0d68w2-4919-4b3b-ae6b-ebb6c3b00css} may be persisted to storage in unencrypted form.
[14:47:22 INF] Now listening on: http://[::]:8267
[14:47:22 INF] Application started. Press Ctrl+C to shut down.
[14:47:22 INF] Hosting environment: Production
[14:47:22 INF] Content root path: /App
[14:47:23 INF] Connecting to mqtt server at core-mosquitto:1883...
[14:47:23 INF] Connecting to mqtt server at core-mosquitto:1883...
[14:47:23 INF] MQTT connected {"primary": true}
[14:47:23 INF] MQTT connected {"primary": false}
If I start ESP-Com with "nodes:" tree defined in config.yaml I get this crash. (my full config.yaml is as the end of the post)
LOG
[08:56:15 INF] Math.NET Numerics Configuration:
Version 5.0.0
Built for .NET 5.0+
Linear Algebra Provider: Managed
Fourier Transform Provider: Managed
Sparse Solver Provider: Managed
Max Degree of Parallelism: 4
Parallelize Elements: 300
Parallelize Order: 64
Check Distribution Parameters: True
Thread-Safe RNGs: True
Operating System: Debian GNU/Linux 12 (bookworm)
Operating System Architecture: X64
Framework: .NET 8.0.1
Process Architecture: X64
[08:56:15 INF] Loading /config/espresense/config.yaml
[08:56:16 WRN] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. For more information go to https://aka.ms/aspnet/dataprotectionwarning
[08:56:16 INF] Attempting to connect to mqtt server at 192.168.178.222:1883 as 29TP_MQTT...
[08:56:16 WRN] No XML encryptor configured. Key {34109288-7e30-495d-bed3-73bccadf8fd8} may be persisted to storage in unencrypted form.
[08:56:16 INF] Optimization enabled
[08:56:16 WRN] Overriding HTTP_PORTS '8080' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'http://+:8267'.
[08:56:16 INF] MQTT connected!
[08:56:16 INF] Now listening on: http://[::]:8267
[08:56:16 INF] Application started. Press Ctrl+C to shut down.
[08:56:16 INF] Hosting environment: Production
[08:56:16 INF] Content root path: /App
[08:56:16 WRN] Unknown node master_bedroom
[08:56:16 INF] HTTP GET /_app/version.json responded 200 in 9.1334 ms
[08:56:16 ERR] BackgroundService failed
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_01.<WriteAsync>b__0() at System.Threading.Tasks.Task
1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 39
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 184
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[08:56:16 FTL] The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost. A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping. To avoid this behavior, configure this to Ignore; however the BackgroundService will not be restarted.
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_01.<WriteAsync>b__0() at System.Threading.Tasks.Task
1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 39
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 184
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[08:56:16 INF] Application is shutting down...
if I start ESP-C without "nodes:" in config.yaml I get this...
LOG
[09:03:11 INF] Math.NET Numerics Configuration:
Version 5.0.0
Built for .NET 5.0+
Linear Algebra Provider: Managed
Fourier Transform Provider: Managed
Sparse Solver Provider: Managed
Max Degree of Parallelism: 4
Parallelize Elements: 300
Parallelize Order: 64
Check Distribution Parameters: True
Thread-Safe RNGs: True
Operating System: Debian GNU/Linux 12 (bookworm)
Operating System Architecture: X64
Framework: .NET 8.0.1
Process Architecture: X64
[09:03:11 INF] Loading /config/espresense/config.yaml
[09:03:11 WRN] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. For more information go to https://aka.ms/aspnet/dataprotectionwarning
[09:03:11 INF] Attempting to connect to mqtt server at 192.168.178.222:1883 as 29TP_MQTT...
[09:03:11 WRN] No XML encryptor configured. Key {8cfe1f07-cf84-4f10-b15d-1e852d9569f9} may be persisted to storage in unencrypted form.
[09:03:11 INF] Optimization enabled
[09:03:11 INF] MQTT connected!
[09:03:11 WRN] Overriding HTTP_PORTS '8080' and HTTPS_PORTS ''. Binding to values defined by URLS instead 'http://+:8267'.
[09:03:11 INF] Now listening on: http://[::]:8267
[09:03:11 INF] Application started. Press Ctrl+C to shut down.
[09:03:11 INF] Hosting environment: Production
[09:03:11 INF] Content root path: /App
[09:03:11 WRN] Unknown node dining_room
[09:03:11 WRN] Unknown node garage
[09:03:11 WRN] Unknown node living_room
[09:03:11 WRN] Unknown node spare_bedroom
[09:03:11 INF] HTTP GET /_app/version.json responded 200 in 13.8885 ms
[09:03:11 WRN] Unknown node charlie_playroom
[09:03:11 WRN] Unknown node master_bedroom
[09:03:11 INF] HTTP GET /api/state/nodes responded 200 in 150.9515 ms
[09:03:11 WRN] Unknown node kitchen
[09:03:12 WRN] Unknown node charlie_bedroom
[09:03:12 WRN] Unknown node office
[09:03:12 WRN] Unknown node hallway
[09:03:12 INF] HTTP GET /api/state/nodes responded 200 in 9.0122 ms
[09:03:13 INF] HTTP GET /api/state/nodes responded 200 in 0.7605 ms
[09:03:14 INF] HTTP GET /api/state/nodes responded 200 in 0.9934 ms
[09:03:15 INF] HTTP GET /api/state/nodes responded 200 in 0.7624 ms
[09:03:16 INF] HTTP GET /api/state/nodes responded 200 in 0.7162 ms
[09:03:16 INF] HTTP GET /_app/version.json responded 200 in 0.5644 ms
[09:03:17 INF] HTTP GET /api/state/nodes responded 200 in 0.5585 ms
[09:03:18 INF] HTTP GET /api/state/nodes responded 200 in 0.7610 ms
[09:03:19 INF] HTTP GET /api/state/nodes responded 200 in 0.5870 ms
[09:03:20 INF] HTTP GET /api/state/nodes responded 200 in 0.5575 ms
[09:03:21 INF] HTTP GET /api/state/nodes responded 200 in 0.7597 ms
BUT It does seem to recognise the nodes before the crash, as if I add "nodes:" back in to config.yaml while ESP-C is running... this happens.
Then this...
LOG
[09:07:28 INF] HTTP GET /_app/version.json responded 200 in 0.1804 ms
[09:07:28 INF] HTTP GET /api/state/nodes responded 200 in 0.2331 ms
[09:07:29 INF] HTTP GET /api/state/nodes responded 200 in 0.2785 ms
[09:07:30 INF] HTTP GET /api/state/nodes responded 200 in 0.2513 ms
[09:07:31 INF] HTTP GET /api/state/nodes responded 200 in 0.2259 ms
[09:07:32 INF] HTTP GET /api/state/nodes responded 200 in 0.2406 ms
[09:07:33 INF] Loading /config/espresense/config.yaml
[09:07:33 INF] HTTP GET /api/state/config responded 200 in 11.0248 ms
[09:07:33 INF] HTTP GET /api/state/config responded 200 in 0.1936 ms
[09:07:33 INF] HTTP GET /api/state/nodes responded 200 in 0.4739 ms
[09:07:33 INF] HTTP GET /_app/version.json responded 200 in 0.1319 ms
[09:07:34 ERR] BackgroundService failed
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_01.<WriteAsync>b__0() at System.Threading.Tasks.Task
1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 39
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 184
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[09:07:34 FTL] The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost. A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping. To avoid this behavior, configure this to Ignore; however the BackgroundService will not be restarted.
SQLite.SQLiteException: database disk image is malformed
at SQLite.PreparedSqlLiteInsertCommand.ExecuteNonQuery(Object[] source)
at SQLite.SQLiteConnection.Insert(Object obj, String extra, Type objType)
at SQLite.SQLiteConnection.Insert(Object obj)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass50_0.b__0(SQLiteConnectionWithLock conn)
at SQLite.SQLiteAsyncConnection.<>c__DisplayClass33_01.<WriteAsync>b__0() at System.Threading.Tasks.Task
1.InnerInvoke()
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at ESPresense.Models.DeviceHistoryStore.Add(DeviceHistory dh) in /App/src/Models/DeviceHistory.cs:line 39
at ESPresense.Locators.MultiScenarioLocator.ExecuteAsync(CancellationToken stoppingToken) in /App/src/Locators/MultiScenarioLocator.cs:line 184
at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
[09:07:34 INF] Application is shutting down...
PLEASE help urgently, i've got a demo on Wednesday to some friends, and would love to hove it working.
Thank you,
Ben
config.yaml
# MQTT Connection, if empty will query and use hassio provided mqtt
mqtt:
host: 192.168.178.222
port: 1883
ssl: false
username: **********
password: **********
# This gets added to the x,y,z to derive a gps location
gps:
latitude: 51.3788810
longitude: -0.9605275
elevation: 0
# How long before device considered stale
timeout: 30
# How long before device is considered away
away_timeout: 120
optimization:
enabled: true
interval_secs: 3600
limits:
absorption_min: 2.5
absorption_max: 3.5
tx_ref_rssi_min: -70
tx_ref_rssi_max: -50
rx_adj_rssi_min: -15
rx_adj_rssi_max: 20
weighting:
algorithm: gaussian
props:
sigma: 0.10
# Floors w/ the points to draw it in meters
floors:
- id: ground_fl
name: "Ground Floor"
# Bounds (x,y,z) of map in meters
bounds: [[0, 0, 0], [12, 10, 2.2]]
rooms:
- name: Kitchendd
points:
- [0, 0]
- [7.5, 0]
- [7.5, 4.3]
- [0, 4.3]
- name: Dining Roomdd
points:
- [7.6, 0]
- [12, 0]
- [12, 4.3]
- [7.6, 4.3]
- name: Living Roomdd
points:
- [7.6, 4.4]
- [12, 4.4]
- [12, 10]
- [7.6, 10]
- name: Charlie's Playroomdd
points:
- [0, 6.1]
- [5.2, 6.1]
- [5.2, 10]
- [0, 10]
- name: Utility Room
points:
- [0, 4.4]
- [3.4, 4.4]
- [3.4, 6.0]
- [0, 6.0]
- name: Hallwaydd
points:
- [5.3, 4.4]
- [7.5, 4.4]
- [7.5, 10]
- [5.3, 10]
- name: Hallway Toilet
points:
- [3.5, 4.4]
- [5.2, 4.4]
- [5.2, 6.0]
- [3.5, 6.0]
- id: first_fl
name: "First Floor"
bounds: [[0, 0, 2.5], [12, 10, 4.7]]
rooms:
- name: Officedd
points:
- [0, 0]
- [4.2, 0]
- [4.2, 4.3]
- [0, 4.3]
- name: Family Bathroom
points:
- [4.3, 0]
- [7.9, 0]
- [7.9, 3.3]
- [5.2, 3.3]
- [5.2, 2.2]
- [4.3, 2.2]
- [4.3, 0]
- name: Charlie Bedroomdd
points:
- [8.0, 0]
- [12, 0]
- [12, 5.0]
- [8.6, 5.0]
- [8.6, 3.3]
- [8.0, 3.3]
- [8.0, 0]
- name: Master Bedroomdd
points:
- [7.6, 4.4]
- [8.5, 4.4]
- [8.5, 5.1]
- [12, 5.1]
- [12, 10]
- [7.6, 10]
- [7.6, 4.4]
- name: Master Bedroom En Suite
points:
- [5.3, 6.7]
- [7.5, 6.7]
- [7.5, 10]
- [5.3, 10]
- name: Spare Bedroomcd
points:
- [5.2, 10]
- [0, 10]
- [0, 6.1]
- [3.5, 6.1]
- [3.5, 4.4]
- [6.5, 4.4]
- [6.5, 6.6]
- [5.2, 6.6]
- name: Spare Bedroom En Suite
points:
- [0, 4.4]
- [3.4, 4.4]
- [3.4, 6.0]
- [0, 6.0]
- name: Landing
points:
- [4.3, 3.4]
- [8.5, 3.4]
- [8.5, 4.3]
- [4.3, 4.3]
- name: Airing Cupboard
points:
- [4.3, 2.3]
- [5.1, 2.3]
- [5.1, 3.3]
- [4.3, 3.3]
- id: outside_world
name: Outside World
bounds: [[-25, -25, 0], [30, 30, 20]]
rooms:
- name: Log Cabinnn
points:
- [2, -8]
- [-2, -8]
- [-2, -12]
- [2, -12]
- name: Garageee
points:
- [3, 10]
- [-3, 10]
- [-3, 16]
- [3, 16]
# Locations of nodes in meters
nodes:
- name: Kitchen
point: [0.2, 0.2, 1.5]
floors: ["ground_fl"]
- name: Living Room
point: [11.2, 9.3, 0.5]
floors: ["ground_fl"]
- name: Dining Room
point: [11.2, 0.8, 0.3]
floors: ["ground_fl"]
- name: Charlie Playroom
point: [4.5, 9.8, 0.5]
floors: ["ground_fl"]
- name: Hallway
point: [6.0, 5.0, 1.5]
floors: ["ground_fl"]
- name: Spare Bedroom
point: [5.0, 9.0, 2.9]
floors: ["first_fl"]
- name: Office
point: [0.0, 2.1, 4.4]
floors: ["first_fl"]
- name: Charlie Bedroom
point: [11.9, 2.9, 2.9]
floors: ["first_fl"]
- name: Garage
point: [-1.5, 14.3, 2]
floors: ["outside_world"]
- name: Log Cabin
point: [0.0, -10, 0.5]
floors: ["outside_world"]
# Devices to track
devices:
- name: "*" # Track all named devices
- id: "node:*"
- id: "tile:*" # Track all tiles
- id: "irk:*" # Track all IRKs
- id: "watch:*"
- id: "phone:*"
- id: "wallet:*"
- id: "keys:*"
- id: "therm:*"
- id: "iBeacon:*"
I'm using a Samsung S20+ (Android) phone with Home Assistant providing a beacon so my phone can be tracked.
In the BLE Transmitter settings I've put my advertise mode at 10Hz and my power at Ultra Low (though I've also tried at high with the same results).
I've flashed 4 ESP32s with the ESPresense firmware and placed them in my office, one at either end of a u shaped hallway, and one in the room adjacent to the office.
I've made no changes to the default configs beyond entering my co-ordinates for the map and telling it where my nodes are located.
I've measure my RSSI@1M using the ESP32 and holding my phone 1M away from it and set it the settings area.
Despite that my device keeps getting lost (I think the beacon just stops reporting since the LastHit is 2 minutes ago and growing), and when it is found it jumps all over the place. When I walk around it tends to take about 60 seconds before it updates where I am (which even at 1Hz should still update within a second of me walking around)
I feel like I'm missing something obvious here, but I'm not sure what it is ๐คฆโโ๏ธ
No response
It would be great if we could see on the map if a node isn't showing a "circle" because it's not connected versus it's just not getting a reading. It would also be nice to be able to display the states of add-on sensors on the map as well, like if motion is triggered, or the temperature.
No response
No response
My map section is stuck on loading
mqtt:
host: 192.168.1.xx
port: 1883
ssl: false
username: xxx
password: xxx
# This gets added to the x,y,z to derive a gps location
gps:
latitude: xx.897957
longitude: -xx.xx6560
elevation: 146
# How long before device considered stale
timeout: 30
# How long before device is considered away
away_timeout: 120
optimization:
enabled: true
interval_secs: 3600
limits:
absorption_min: 2.5
absorption_max: 3.5
tx_ref_rssi_min: -70
tx_ref_rssi_max: -50
rx_adj_rssi_min: -15
rx_adj_rssi_max: 20
weighting:
algorithm: gaussian
props:
sigma: 0.10
# Floors w/ the points to draw it in meters
floors:
- id: ground
name: Ground Floor
rooms:
- name: Office
points:
- [0, 9.22]
- [5.79, 9.22]
- [5.79, 5.97]
- [0, 5.97]
- [0, 9.22]
- name: Garage
points:
- [2.97, 5.97]
- [5.79, 5.97]
- [5.79, 0]
- [2.97, 0]
- [2.97, 5.97]
- name: Foyer
points:
- [0, 5.97]
- [2.97, 5.97]
- [2.97, 0]
- [0, 0]
- [0, 5.97]
- id: first
name: First Floor
# Bounds (x,y,z) of map in meters
rooms:
- name: Kitchen
points:
- [0, 8.28]
- [5.79, 8.28]
- [5.79, 4.62]
- [0, 4.62]
- [0, 8.28]
- name: Living Room
points:
- [0, 4.62]
- [5.79, 4.62]
- [5.79, 0]
- [0, 0]
- [0, 4.62]
- id: second
name: Second Floor
rooms:
- name: Bedroom
points:
- [0, 8.28]
- [5.79, 8.28]
- [5.79, 4.62]
- [0, 4.62]
- [0, 8.28]
- name: Other Rooms
points:
- [0, 4.62]
- [5.79, 4.62]
- [5.79, 0]
- [0, 0]
- [0, 4.62]
# Locations of espresense nodes in meters
nodes:
- name: Bedroom
point: [0, 2, 0]
floors: ["second"]
- name: Garage
point: [2, 0, 1]
floors: ["ground"]
- name: Office
point: [1, 0, 0.5]
floors: ["ground"]
- name: Living Room
point: [0.25, 0.4, 0.3]
floors: ["first"]
- name: Kitchen
point: [0, 3, 0.85]
floors: ["first"]
# Devices to track
devices:
- id: "iBeacon:879c94c5xxxxxxxxxxxxxxxxxxxx-0"
- id: "irk:21365xxxxxxxxxxxxxxxxxx"
It seems like the config / calibration is persisted in mqtt messages, the issue is those go away if I reboot Mosquitto. I'd like them to be persisted someplace where they survive a hard reboot for the server. I've mitigated it a little by moving the MQTT server out of HA into it's own container on proxmox which at least means I don't lose the config on every HA operating system update ...
if you try to set for example irk:fb153e4e80d2d1a51bc91a8162e9fa71
as device id you get the following error
[00:41:13 ERR] Error reading config, ignoring... (Line: 94, Col: 20, Idx: 2161) - (Line: 94, Col: 30, Idx: 2171): Exception during deserialization
I noticed a higher load average on my system and realized it was caused by this addon. I don't have any specific information about what might have been causing this, but I know this is in early development so I thought I'd report it so you're aware.
Otherwise, addon has been great and excited to see where things go with it :)
At the moment, if I restart the integration while a device isnโt in range of my nodes, the integration wont update its MQTT entity to away, nor even keep displaying it on the devices tab.
Itโd be nice to have the integration update each MQTT entity to away if it hasnโt been seen by the integration after startup.
Also, Iโve noticed that sometimes some devices become stuck & keep reporting as being in a specific room even when theyโre not in Bluetooth range anymore.
I have recently installed and configured ESPresense-companion and, apart from realising I need to add many more nodes, I am finding the following log item being generated 2-3 times per minute after ESPresense-companion optimiser has started running:
[07:50:27 INF] Optimizer Absorption NelderMead found worse results, rms 179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000>179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000
The values appear to be extreme. Is this normal? Can you recommend how to resolve it if is indeed irregular?
Thanks
Im struggling to get my head around the floor layout, I think the issue is with my bounds, the map shown is flipped vertically:
This:
should really be orientated like this
with some padding the left and right, but im not sure how to achieve this.
Also,I set the GPS coordinates to the most south westerly point, ie the "office" but very few devices are appearing in a room:
This is the yaml im using
floors:
- id: ground
name: Ground Floor
bounds:
- - 0
- 0
- 0
- - 29.58
- 29.58
- 6.76
rooms:
- name: office
points:
- - 0
- 0
- - 3
- 0
- - 3
- 5.0
- - 0
- 5.00
- - 0
- 0
- name: DiningRoom
points:
- - 14.47
- 3.59
- - 18.98
- 3.59
- - 18.98
- 6.76
- - 14.47
- 6.76
- - 14.47
- 3.59
- name: kitchen
points:
- - 18.96
- 3.59
- - 23.44
- 3.59
- - 23.44
- 6.76
- - 18.96
- 6.76
- - 18.96
- 3.59
- name: RearLounge
points:
- - 23.43
- 2.95
- - 25.75
- 2.95
- - 25.75
- 6.76
- - 23.43
- 6.76
- - 23.43
- 2.95
- name: Lounge
points:
- - 25.75
- 1.26
- - 29.58
- 1.26
- - 29.58
- 6.78
- - 25.75
- 6.78
- - 25.75
- 1.26
- name: BackHall
points:
- - 23.47
- 0.78
- - 25.75
- 0.78
- - 25.75
- 2.95
- - 23.47
- 2.95
- - 23.47
- 0.78
- name: Hall
points:
- - 25.75
- 0.17
- - 29.57
- 0.17
- - 29.57
- 1.27
- - 25.75
- 1.27
- - 25.75
- 0.17
- id: first
name: first Floor
bounds:
- - 0
- 0
- 3.1
- - 29.58
- 6.78
- 6.76
rooms:
- name: Ryan
points:
- - 2.9
- 0
- - 6.15
- 0
- - 6.15
- 3.79
- - 2.9
- 3.79
- - 2.9
- 0
- name: Bedroom
points:
- - 0
- 0
- - 2.89
- 0
- - 2.89
- 3.78
- - 0
- 3.78
- - 0
- 0
This is one that I think might help in terms of calibration.
It would be nice if it was possible to define a "hard border" for trilateralization results.
For instance consider this scenario:
Where the "Basement Theater" ESPresense node is, there's actually a solid foundation wall. However, as can be seen there, because of the distance interplays involved (variations from in-pocket to out-pocket for the phone, and just general floopiness of measurement), ESPresense is choosing a solution that is physically impossible by placing my phone outside this wall.
The stopgap is, of course and as seen there, to simply make the room "bigger" but then the room also does not reflect reality.
What I'd propose is the ability to set a "boundary room". Then, during trilateralization calculations, if a possible solution is outside of that boundary, it is rejected as impossible and the next potential solution is checked, and so on.
By doing it this way, one could calibrate this in places where it make sense (e.g. in a basement or a second story where it is physically impossible to go beyond the walls) while leaving the possibility of an open-ended space if it is not defined (e.g. on a first story).
So I finally got everything setup. And Im also getting unexpected results
I've got rooms and two floors. I have espresense nodes over two floor.
Now for testing, I just focused on a single floor.
Initially I saw the devices in the wrong places, thinking this was due to the number of sensors, I then change the second floor nodes so they are on first floor but higher. However this made no difference.
Looking at the ipad, espresnese itself thinks it is connected to the frontroom sensor, but this isnt even showing as one of the three for the mapping sensors for companion.
What occurred to me was I have brick walls, and this will be impacting the distance. So maybe when we draw walls we need to provide a correction factor due to the wall, some manual value we can derive from testing.
And using the sensors over the many floors, will also be handy as people who dont have concrete floors will be able to take advantage of the 3 dimensions for mapping.
But myAnd using the sensors over the many floors, will also be handy as people who dont have concrete floors will be able to take advantage of the 3 dimensions for mapping. overwhelming view is that ESPresense companion is starting to look like a viable option to give a position in a room, but it clearly needs tweaking.
Originally posted by @rhamblen in #94 (comment)
got interested in locting BT-devices wie ESPRENSE, but to much variation in simple RSSI.
do you have achieved a accuray better than 1,5m ( shorter distance means closer to the original location)?
I am running espresense with 5 nodes in a two-story home and companion app show the lateral position on the map pretty accurately. But where its having problem is figuring the height/floor. Actually that is correct technically, since I can see the solution for second floor has much smaller error than the solution for first floor. But since both have the same confidence, its reporting first floor as best scenario (true location is second floor). Also the device_tracker entity in home assistant does not provide all of these info so I cannot create another sensor on top of it to fix the issue.
3.3.1
No response
No response
No response
No response
No response
No response
No response
Also the release notes button in the adding shows 'initial release' with 0.0.0
Would it help if I'd take some time on writing up a PR accordingly?
I added the repository, added the ESPresense Companion, added the companion to my Sidebar and opened it up. I had a few problems. I totally understand this is an early release, I just wanted to share what I found.
Firstly the Settings link 404s. It seems to be pointing at a http://<insert Home Assistant name/IP here>:8123/settings
<a href="/settings" class="svelte-r1ko2w">Settings</a>
Secondly, the link in the add-on's info page for, "Visit the ESPresense Companion page for more details." just goes to the root of ESPresense.com. I poked around the ESPresense.github.io repository, but couldn't find the new page, yet.
The diagram seems to show a number of rooms and base stations which don't align with the name's of my rooms and/or base stations.
I tried removing the add-on, its repository and re-installing a couple times. It didn't seem to change anything for me.
Anybody have any idea how the "Front end updated, refresh" prompt works for the HA front end? We need something like that.
Workaround: Right click > Inspect > Right click Reload (in toolbar) and pick "Empty Cache and Hard Reload"
Hello. I use Espresense Companion for a few things, but one of them is tracking whether or not my trash bin is out. I track the trash collection days and I can set reminders and alerts to bug me to put the trash out. It's a cool and fun automation that I actually get a lot of functional use out of. My trash bin has a BLE Beacon attached to it.
The problem is, the software has a lot of trouble figuring out where it is when it's out (it also has a lot of trouble with it in general, even when not out). I have brick walls which obviously cause a lot of issues trying to track something outside, however I can consistently have 5+ nodes connected to the trash bin even when it's out on the street.
See the image below, with the red "X" I drew indicating the bin's actual location.
Looking at the data in the rings, I can see how making a determination on the distances of connected ESP32's alone will be difficult. Both intersections of the pink (Kitchen) and grey (Office) circles (which are the closest two circles) have pretty equal values. I'm not sure if it could also be biased by attempting to keep tracked objects inside the marked house. I haven't checked to see if that is apart of the algorithm.
This problem perplexed me, the best solution would be to have a much better placed ESP32, but that isn't possible. It would have to be outside, where I don't have outlets (and I would need to waterproof it), or the south most point of the Garage, which also doesn't have outlets.
It perplexed me until I considered that simply having 5 connected node distances isn't the only data I have. I also have a lack of data from nodes that are unable to connect to the trash bin beacon.
Looking back at the image I shared, the Trash Bin Beacon is nearly on top of the Living Room Node. This certainly cannot be true, because the Living Room node isn't able to detect the beacon at all!
So I propose a change to how the algorithm handles cases where confidence of the location is low. (In the image I provided, the confidence of the location is low -- around 25 max, mostly hovering at 22.
If the confidence is very low, the software should also "push" the beacon away from nodes that, based on predicted location, should be connected but are not. Like my Living Room Node, in this example.
I would like the developer's thoughts on this. Some other things I would like is the ability to specify that some beacons will never be X meters away from or close to a node. Like my Trash Bin will never be 5 meters or less away from the Living Room node, or 10 meters or less away from my Master Bedroom node. This could help in cases like Pets (with beacon collars) that aren't allowed in specific rooms, as well.
I dont know how to explain, tracked device position is very unstable and nodes changes their coverage area.
please look at the screen recording
Config:
# MQTT Connection, if empty will query and use hassio provided mqtt
mqtt:
host: homeassistant.local
port: 1883
ssl: false
username: my_username
password: my_password
# This gets added to the x,y,z to derive a gps location
gps:
latitude: 38.897957
longitude: -77.036560
elevation: 146
# How long before device considered stale
timeout: 30
# How long before device is considered away
away_timeout: 120
optimization:
enabled: true
interval_secs: 60
limits:
absorption_min: 2.5
absorption_max: 3.5
tx_ref_rssi_min: -70
tx_ref_rssi_max: -50
rx_adj_rssi_min: -15
rx_adj_rssi_max: 20
weighting:
algorithm: gaussian
props:
sigma: 0.10
# Floors w/ the points to draw it in meters
floors:
- id: first
name: First Floor
# Bounds (x,y,z) of map in meters
bounds: [[0, 0, 0], [18.5, 19.2, 1.5]]
rooms:
- name: Garage
points:
- [0, 0]
- [5.5, 0]
- [5.5, 6]
- [0, 6]
- name: Kitchen
points:
- [0, 6]
- [0, 13.2]
- [0.5, 13.2]
- [1, 13.5]
- [2.75, 13.5]
- [3.25, 13.2]
- [3.75, 13.2]
- [3.75, 6]
- name: Living Room
points:
- [3.75, 6]
- [3.75, 11.5]
- [9.5, 11.5]
- [9.5, 5]
- [5.5, 5]
- [5.5, 6]
- name: Suite Living Room
points:
- [3.75, 11.5]
- [6.75, 11.5]
- [6.75, 17.25]
- [3.75, 17.25]
- name: Suite Bedroom
points:
- [6.75, 14.5]
- [9.5, 14.5]
- [9.5, 17.25]
- [6.75, 17.25]
- name: Suite Bathroom
points:
- [6.75, 14.5]
- [9.5, 14.5]
- [9.5, 11.5]
- [6.75, 11.5]
- name: Foyer
points:
- [5.5, 5]
- [9, 5]
- [9, 2.1]
- [5.5, 2.1]
- name: Hallway
points:
- [9, 5]
- [11.2, 5]
- [11.2, 6.25]
- [12.2, 6.25]
- [12.2, 4]
- [9, 4]
- name: Guest Bathroom
points:
- [9.5, 5]
- [9.5, 8.75]
- [11.2, 8.75]
- [11.2, 5]
- name: Master Bathroom
points:
- [9.5, 8.75]
- [9.5, 12.2]
- [11.2, 12.2]
- [11.2, 8.75]
- name: Master Bedroom
points:
- [11.2, 12.2]
- [15.7, 12.2]
- [15.7, 5.5]
- [12.2, 5.5]
- [12.2, 6.25]
- [11.2, 6.25]
- name: Guest Bedroom
points:
- [12.2, 5.5]
- [15.7, 5.5]
- [15.7, 0]
- [12.2, 0]
- name: Office
points:
- [9, 4]
- [12.2, 4]
- [12.2, 0]
- [9, 0]
# Locations of espresense nodes in meters
nodes:
- name: Living Room
point: [9.2, 9.5]
floors: ["first"]
- name: Office
point: [10.2, 0.1]
floors: ["first"]
- name: Kitchen
point: [0.1, 7.75]
floors: ["first"]
- name: Suite Living Room
point: [3.85, 16]
floors: ["first"]
- name: Master Bedroom
point: [13.1, 12]
floors: ["first"]
# Devices to track
devices:
- id: myname_s_iphone_15_pro_ble
name: MyName's iPhone 15 Pro BLE
- id: wifename_s_iphone
name: WifeName's iPhone BLE
Error Log:
[17:37:38 INF] Loading /config/espresense/config.yaml
Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
at ESPresense.Models.Node.Update(Config c, ConfigNode cn, IEnumerable`1 floors) in /App/Models/Node.cs:line 48
at ESPresense.Models.State.<.ctor>g__LoadConfig|0_1(Config c) in /App/Models/State.cs:line 26
at ESPresense.Models.State..ctor(ConfigLoader cl) in /App/Models/State.cs:line 68
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.ConstructorInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host)
at Program.<Main>$(String[] args) in /App/Program.cs:line 95
Hello,
I have area that open floor plan, where kitchen, dining room, and family room all large room. what would be best naming practices for devices that are on in a corner and results could more than one room?
In the log all devices come up as invalid nodes and I think as a result nothing populates when the web interface is launched.
Upon installation and starting, the ESPresense-companion will max out my CPU to 99.6%. Starting the web UI I just get a "loading" screen with the 5 sidebar buttons but they don't respond when clicked on.
Machine:
i9-10900 w/ 4 cores allotted to it on VM (proxmox) w/ 8gb RAM
I've struggled to find an easy way to change the Y value display reference scaling (currently has a scaling reference that looks to be aligned to the bounding area. This causes the display to skew the representation.
I thought as an enhancement to the project could be some way to modify the view in terms of scaling to bounding area, scaling 100%, zoom/zoom out for possibly some larger implementations.
I scrunch up the display window for now when I want things to look normal
I just installed the latest espresense-companion (0.6.5) Opening the interface causes it to continuously reload. I purged the cookies and site data. Then the interface worked again. But the issue came right back. This is log output.
[12:20:55 INF] Content root path: /App
[12:20:56 INF] MQTT connected!
[12:20:59 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 32.2609 ms
[12:20:59 INF] HTTP GET /_app/version.json responded 200 in 12.1795 ms
[12:20:59 INF] HTTP GET /api/state/config responded 200 in 213.6327 ms
[12:20:59 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.2105 ms
[12:20:59 INF] HTTP GET /api/state/config responded 200 in 3.6130 ms
[12:20:59 INF] HTTP GET /_app/version.json responded 200 in 1.9188 ms
[12:20:59 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1451 ms
[12:20:59 INF] HTTP GET /api/state/config responded 200 in 0.5892 ms
[12:20:59 INF] HTTP GET /_app/version.json responded 200 in 0.4093 ms
[12:20:59 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1715 ms
[12:21:00 INF] HTTP GET /api/state/config responded 200 in 0.7817 ms
[12:21:00 INF] HTTP GET /_app/version.json responded 200 in 0.3849 ms
[12:21:00 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1748 ms
[12:21:00 INF] HTTP GET /api/state/config responded 200 in 0.5521 ms
[12:21:00 INF] HTTP GET /_app/version.json responded 200 in 0.3990 ms
[12:21:00 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1447 ms
[12:21:00 INF] HTTP GET /api/state/config responded 200 in 0.5851 ms
[12:21:00 INF] HTTP GET /_app/version.json responded 200 in 0.3714 ms
[12:21:01 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.3877 ms
[12:21:01 INF] HTTP GET /api/state/config responded 200 in 2.2862 ms
[12:21:01 INF] HTTP GET /_app/version.json responded 200 in 0.7779 ms
[12:21:01 INF] HTTP GET /api/state/config responded 200 in 0.6752 ms
[12:21:01 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1616 ms
[12:21:01 INF] HTTP GET /_app/version.json responded 200 in 0.8337 ms
[12:21:01 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1531 ms
[12:21:01 INF] HTTP GET /api/state/config responded 200 in 0.5229 ms
[12:21:01 INF] HTTP GET /_app/version.json responded 200 in 0.4863 ms
[12:21:01 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.3920 ms
[12:21:01 INF] HTTP GET /api/state/config responded 200 in 1.3393 ms
[12:21:01 INF] HTTP GET /_app/version.json responded 200 in 0.3371 ms
[12:21:02 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.2766 ms
[12:21:02 INF] HTTP GET /api/state/config responded 200 in 1.0665 ms
[12:21:02 INF] HTTP GET /_app/version.json responded 200 in 0.8151 ms
[12:21:02 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.6617 ms
[12:21:02 INF] HTTP GET /api/state/config responded 200 in 1.2219 ms
[12:21:02 INF] HTTP GET /_app/version.json responded 200 in 0.3265 ms
[12:21:02 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1998 ms
[12:21:02 INF] HTTP GET /api/state/config responded 200 in 0.5435 ms
[12:21:02 INF] HTTP GET /_app/version.json responded 200 in 0.4489 ms
[12:21:02 INF] HTTP GET /_app/immutable/chunks/Map.61C9N8k4.js responded 404 in 0.1102 ms
[12:21:02 INF] HTTP GET /api/state/config responded 200 in 0.4273 ms
[12:21:02 INF] HTTP GET /_app/version.json responded 200 in 0.3518 ms
Use case: I have multiple floors in my house (4) and I'm currently expirementing with companion on single one. Before I was using standalone espresense with range filtration to detect people in the room. I'd like to swtich entirely to companion but it requires at least 3 fixes for devices in order to be "located'. Which is not really possible while I haven't setup 20+ nodes (multifloor is not really possible here)
It would be great if I can keep for selected floor current config (for experimenting and testing config and new versions) but set other selected floors as "locate device at node coordinates as soon as this node is closest to devices and within node configured range"
i.e
floors:
- id: f2
name: floor 2
lateralizer: nearest_node # (current whatever named as default)
bounds: [[0, 0, 6], [12, 7, 8.8]]
rooms: [] #
nodes:
- name: f2_bedroom
point: [8, 0.10, 6.70]
filter:
range: 2.0 # (and\or configured via node settings in UI)
floors: ["f2"]
I see some code related to that, but I'm not really sure whether it works at all and\or configurable per floor
Is the Gaussian function written correctly? Maybe I missed something but it looks like it's missing a power in the first sigma term?
var y = 1d / Math.Sqrt(_sigma * 2d * Math.PI) * Math.Exp(-(Math.Pow(x, 2d) / (2d * Math.Pow(_sigma, 2d))))
should this be:
var y = 1d / Math.Sqrt(Math.Pow(_sigma, 2d)* 2d * Math.PI) * Math.Exp(-(Math.Pow(x, 2d) / (2d * Math.Pow(_sigma, 2d))))
[17:16:34 ERR] Failed to get MQTT config from Hass Supervisor
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Http.HttpConnectionResponseContent'.
at System.Net.Http.HttpContent.ReadAsStringAsync(CancellationToken cancellationToken)
at Flurl.Http.FlurlResponse.GetJsonAsyncT
at ESPresense.Services.MqttCoordinator.GetClient() in /App/src/Services/MqttCoordinator.cs:line 53
[17:16:34 INF] Now listening on: http://[::]:8267
[17:16:34 INF] Application started. Press Ctrl+C to shut down.
[17:16:34 INF] Hosting environment: Production
[17:16:34 INF] Content root path: /App
[17:16:34 INF] Connecting to mqtt server at localhost:1883...
[17:16:34 INF] MQTT {"primary": true} disconnected
[17:16:34 ERR] MQTT {"primary": true} connection failed Connecting with MQTT server failed (NotAuthorized).: null
This started suddenly in the last few versions (after v0.3.27) but I'm not 100% sure which one from my cursory look over the changelogs.
I've got two explicitly configured iBeacon
devices like so:
253 # Devices to track
254 devices:
255 - id: "iBeacon:fdbb94fc-5d04-4dd1-a85c-85430d91812b-100-1"
256 name: "Joshua's Phone"
257 - id: "iBeacon:33e6536e-1e48-46dc-9c4e-ace9b9e04ee6-100-1"
258 name: "Michael's Phone"
However, the companion is generating several other "devices" with the same name, but with different ID formats and which show different locations:
Not sure if this is a bug or a side-effect of a recent config change (e.g. what prompted 838ea11) that I've missed, so advice would be appreciated :-)
Hi,
I run Home Assistant without the supervisor and therefore cannot use the addon store.
Is this possible to run directly in docker?
Are there any install instructions for that?
but get in status form multible stations
config
# MQTT Connection, if empty will query and use hassio provided mqtt
mqtt:
host:
port: 1883
ssl: false
username:
password:
# Bounds (x,y,z) of map in meters
bounds: [[-1, -1, -1], [30, 30, 5]]
# How long before device considered stale
timeout: 30
# How long before device is considered away
away_timeout: 120
# Floors w/ the points to draw it in meters
floors:
- name: First Floor
z: 1 # Elevation in meters
rooms:
- name: Schlafen
points:
- [8.4, 9.80]
- [8.4, 13.75]
- [12.3, 13.75]
- [12.3, 10.25]
- [14.1, 10.25]
- [14.1, 7.7]
- name: Bad_Hinten
points:
- [14.2, 7.65]
- [19.2, 5]
- [19.2, 10]
- [14.2, 10]
- name: Buero
points:
- [15.6, 10.40]
- [19.2, 10.40]
- [19.2, 13.55]
- [15.6, 13.55]
- name: Gang_hinten
points:
- [12.5, 10.45]
- [15.45, 10.45]
- [15.45, 13.55]
- [12.5, 13.55]
- name: Wohnzimmer
points:
- [9.6, 14]
- [14, 14]
- [14, 23.15]
- [9.6, 23.15]
- name: Bad_Vorne
points:
- [14.25, 14.15]
- [16.20, 14.15]
- [16.20, 16.5]
- [14.25, 16.5]
- name: Gang
points:
- [14.25, 16.7]
- [16.20, 16.7]
- [16.20, 20.2]
- [14.25, 20.2]
- name: Kueche
points:
- [16.5, 14.15]
- [20.20, 14.15]
- [20.20, 18.4]
- [16.5, 18.4]
- name: Henne
points:
- [16.5, 18.6]
- [20.20, 18.6]
- [20.20, 23]
- [16.5, 23]
# Locations of espresense nodes in meters
nodes:
- name: henne
point: [20, 22.75, 1.87]
- name: wohnzimmer2
point: [13.98, 22.8, 0.2]
- name: wohnzimmer
point: [10.2, 14.51, 0.4]
- name: gang
point: [16.14, 18.3, 0.5]
- name: bad_vorne
point: [14.34, 15, 2]
- name: kueche
point: [16.55, 14.22, 2.3]
- name: buero
point: [18.75, 10.425, 0.1]
# Devices to track
devices:
- name: "Henne_Handy_hps"
id: irk:fb153e4e80d2d1a51bc91a8162e9fa71
version 0.1.11 and 0.1.10
It seems "best_scenario" field shows only a floor, but the same time in web UI you can see also the room. Should it show the same thing?
Hi
I have home assistant core running on unraid in a docker.
As such I cant use ESPresense companion.
Is there anyway it can be an integration rather than an addon, so we can load it from HACS?
Or can it be a stand along app?
I finally got this mostly setup. Ive made my floorplan and labeled my nodes and their location but they all show inactive and no devices, is there another step i'm missing to link to my espresense nodes?
I have setup a MQTT server and can see the espresense devices in home assistant.
I can see my nodes in the node list. They are all green and I have buttons for update and visit for 3 out of the 4 I have setup.
Devices showed my configured phone once but never updated or gave me any data except n/a or 0.
I've noticed that the current algorithm has a few problems. Devices will bounce around the room randomly and sometimes appear in other rooms for a few seconds. The floor detection is also quite unreliable for me.
I think a machine learning model could probably do a much better job at estimating device positions and which floor they are on. It would be great if I could go around my house and take multiple measurements at various points. Some where I am holding my phone, some where it's in my pocket, etc. Then use this data to train a model to estimate my position in the house. I think I'm collecting more than enough data to do this accurately and reliably (16 ESPresense nodes for 4 devices), but I just need to train a model to filter out some of the noise.
Has anyone worked on something like this before? Is there a plugin or fork that I could try out? (I remember reading a blog post a while ago from someone who did something like this, but I don't think it was related to ESPresense.)
(I don't know why Dining
doesn't show up on the left hand side.)
How can I improve calibration? In reality my phone is at the red X with direct line of sight to livingroom01/02/03
and dining
, with a single wall between it and kitchen
. Here it's a good 7m away from the actual position and is never closer than 3m from the actual position.
The output coordinates of each of the three devices I am tracking is fairly accurate (to within a couple meters) but the chosen room is incorrect. Digging in a little deeper it looks like for some reason the localization algorithm is timing out or running through too many iterations and defaulting to a confidence of 1 for each floor which is then confusing the Best Scenario room and possibly causing an issue with plotting the tracked devices on the map. I have attached a screenshot from one of the tracked devices. In that screenshot the tracker is physically in the "Back Room" on the "First floor" and the coordinates properly reflect that but it is being reported as being in the "Basement"
Summary of issues being encountered:
-Best Scenario room is always wrong (seems to be stuck on "Basement" for all devices)
-Devices are not plotted on the map (on any floor)
-The "Confidence" for a specific device being on all floors is 1
-The "ReasonForExit" for all floors is "ExceedIterations"
Does the algorithm not do well with too many base stations? I currently have 12 active base stations
Hi I appreciate it's still WIP but wondered if there is any documentation or a setup guide/video?
Many thanks
Andy
Since boundaries are not only set in x and y but in z as well it should be rather easy to show a multi-story home from the side. This would improve usability and overview.
Please add a visualisation from the side (from x or y axis) In addition to the top-down view (from the z-axis).
Best case: A semi-transparent rotatable 3D-Object showing all floors
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.