Skip to content

Copilot/create unified driver mechanism#10

Open
maikebing wants to merge 5 commits intomasterfrom
copilot/create-unified-driver-mechanism
Open

Copilot/create unified driver mechanism#10
maikebing wants to merge 5 commits intomasterfrom
copilot/create-unified-driver-mechanism

Conversation

@maikebing
Copy link
Copy Markdown
Member

No description provided.

Copilot AI and others added 4 commits April 15, 2026 20:14
Agent-Logs-Url: https://github.com/IoTSharp/Gateways/sessions/bf30490c-271b-47f0-8c48-ebb460f37aa9

Co-authored-by: maikebing <3445167+maikebing@users.noreply.github.com>
Agent-Logs-Url: https://github.com/IoTSharp/Gateways/sessions/bf30490c-271b-47f0-8c48-ebb460f37aa9

Co-authored-by: maikebing <3445167+maikebing@users.noreply.github.com>
Agent-Logs-Url: https://github.com/IoTSharp/Gateways/sessions/bf30490c-271b-47f0-8c48-ebb460f37aa9

Co-authored-by: maikebing <3445167+maikebing@users.noreply.github.com>
Agent-Logs-Url: https://github.com/IoTSharp/Gateways/sessions/bf30490c-271b-47f0-8c48-ebb460f37aa9

Co-authored-by: maikebing <3445167+maikebing@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 16, 2026 03:00
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a unified driver-based gateway scaffold across backend (Domain/Application/Infrastructure), hosting (Web API + Worker), persistence (SQLite), upload transports (HTTP/MQTT), and a Vue 3 admin shell (src/gateway-web) to browse/configure and debug runtime read/write.

Changes:

  • Added DDD-style backend projects (Domain/Application/Infrastructure) implementing unified driver contracts, a driver catalog, runtime orchestration, and SQLite persistence.
  • Added ASP.NET Core minimal API + Worker host to expose configuration/runtime endpoints and run polling tasks.
  • Added a Vue 3 + Vite frontend shell with navigation and resource panels for drivers/channels/devices/points/tasks/transforms/uploads/runtime.

Reviewed changes

Copilot reviewed 90 out of 149 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/gateway-web/vite.config.ts Vite config with Vue plugin, devtools plugin, and @ alias.
src/gateway-web/tsconfig.node.json Node-side TS config for tooling configs (vite/vitest/etc.).
src/gateway-web/tsconfig.json TS project references for app + node configs.
src/gateway-web/tsconfig.app.json App TS config extending Vue DOM defaults and path mapping.
src/gateway-web/src/views/UploadsView.vue UI panel for upload channels and upload routes.
src/gateway-web/src/views/TransformsView.vue UI panel for transform rules.
src/gateway-web/src/views/TasksView.vue UI panel for polling tasks.
src/gateway-web/src/views/RuntimeView.vue UI for debug read/write against runtime endpoints.
src/gateway-web/src/views/PointsView.vue UI panel for points.
src/gateway-web/src/views/DriversView.vue Drivers catalog view driven by Pinia store.
src/gateway-web/src/views/DevicesView.vue UI panel for devices.
src/gateway-web/src/views/DashboardView.vue Dashboard/overview landing page.
src/gateway-web/src/views/ChannelsView.vue UI panel for channels.
src/gateway-web/src/stores/gateway.ts Pinia store for loading driver catalog.
src/gateway-web/src/router/index.ts Frontend routes for dashboard and configuration sections.
src/gateway-web/src/main.ts Vue app bootstrap (Pinia + router).
src/gateway-web/src/components/ResourcePanel.vue Reusable resource fetch/refresh + JSON rendering panel.
src/gateway-web/src/assets/main.css Base styling for layout/panels/navigation.
src/gateway-web/src/api.ts Fetch wrapper for JSON GET/POST against backend API.
src/gateway-web/src/App.vue Main layout with sidebar navigation and router outlet.
src/gateway-web/public/favicon.ico Frontend favicon asset.
src/gateway-web/package.json Frontend dependencies and build/typecheck scripts.
src/gateway-web/index.html Vite HTML entry.
src/gateway-web/env.d.ts Vite client types reference.
src/gateway-web/README.md Default Vue/Vite template README for the frontend project.
src/gateway-web/.vscode/extensions.json Recommends Volar extension.
src/gateway-web/.gitignore Frontend-specific ignores (dist/node_modules/etc.).
src/IoTSharp.Gateways.Worker/appsettings.json Worker settings (SQLite connection, logging).
src/IoTSharp.Gateways.Worker/appsettings.Development.json Worker dev logging config.
src/IoTSharp.Gateways.Worker/Properties/launchSettings.json Worker launch profile.
src/IoTSharp.Gateways.Worker/Program.cs Worker host setup + schema init + polling worker registration.
src/IoTSharp.Gateways.Worker/IoTSharp.Gateways.Worker.csproj Worker project definition and references.
src/IoTSharp.Gateways.Worker/GatewayPollingWorker.cs Background polling loop invoking runtime service per task.
src/IoTSharp.Gateways.Infrastructure/Uploads/GatewayUploads.cs HTTP + MQTT upload transports and registry.
src/IoTSharp.Gateways.Infrastructure/Persistence/SqliteGatewayPersistence.cs SQLite schema init + repository + connection factory.
src/IoTSharp.Gateways.Infrastructure/IoTSharp.Gateways.Infrastructure.csproj Infrastructure packages and references (Dapper/Sqlite/MQTTnet/IoTClient).
src/IoTSharp.Gateways.Infrastructure/GatewayInfrastructureServiceCollection.cs DI registration for drivers, repository, uploads, and infra services.
src/IoTSharp.Gateways.Infrastructure/Drivers/GatewayDrivers.cs IoTClient-backed driver adapters + registry implementation.
src/IoTSharp.Gateways.Domain/IoTSharp.Gateways.Domain.csproj Domain project definition.
src/IoTSharp.Gateways.Domain/GatewayModel.cs Domain enums/models + unified driver & upload contracts.
src/IoTSharp.Gateways.Application/IoTSharp.Gateways.Application.csproj Application project definition.
src/IoTSharp.Gateways.Application/GatewayApplication.cs Repository contract + configuration/runtime/catalog/transformation services.
src/IoTSharp.Gateways.Api/appsettings.json API settings (SQLite connection, logging, allowed hosts).
src/IoTSharp.Gateways.Api/appsettings.Development.json API dev logging config.
src/IoTSharp.Gateways.Api/Properties/launchSettings.json API launch profiles/urls.
src/IoTSharp.Gateways.Api/Program.cs Minimal API endpoints for config + runtime read/write/poll + CORS.
src/IoTSharp.Gateways.Api/IoTSharp.Gateways.Api.http HTTP scratch file for testing endpoints.
src/IoTSharp.Gateways.Api/IoTSharp.Gateways.Api.csproj API project definition and references.
README.md New root README describing layered architecture and run/build steps.
IoTSharp.Gateways.sln Updated solution structure to include layered projects and worker/api.
.gitignore Expanded ignores for bin/obj and frontend build artifacts.
Files not reviewed (1)
  • Data/Migrations/20221029113750_CreateIdentitySchema.Designer.cs: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +34
public sealed class SqliteGatewayConnectionFactory : IGatewayDbConnectionFactory
{
private readonly GatewayStorageOptions _options;

public SqliteGatewayConnectionFactory(IOptions<GatewayStorageOptions> options)
{
_options = options.Value;
Batteries_V2.Init();
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SqliteGatewayConnectionFactory calls SQLitePCL.Batteries_V2.Init() and imports SQLitePCL, but IoTSharp.Gateways.Infrastructure.csproj does not reference any SQLitePCLRaw/* package. This will fail to compile/restore. Either remove the SQLitePCL dependency (not needed when using Microsoft.Data.Sqlite) or add the appropriate SQLitePCLRaw bundle package.

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +34
var client = _httpClientFactory.CreateClient(nameof(HttpUploadTransport));
var settings = GatewayJson.Parse(channel.SettingsJson);
if (settings.TryGetValue("headerName", out var headerName) && !string.IsNullOrWhiteSpace(headerName) && settings.TryGetValue("headerValue", out var headerValue) && !string.IsNullOrWhiteSpace(headerValue))
{
client.DefaultRequestHeaders.Remove(headerName);
client.DefaultRequestHeaders.Add(headerName, headerValue);
}

if (settings.TryGetValue("bearerToken", out var bearerToken) && !string.IsNullOrWhiteSpace(bearerToken))
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", bearerToken);
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HttpUploadTransport mutates HttpClient.DefaultRequestHeaders per upload based on per-channel settings. Since HttpClient instances from IHttpClientFactory are pooled/reused, this can leak headers across different channels/requests and is not safe under concurrent uploads. Prefer setting headers on a per-request HttpRequestMessage (or create a dedicated named client per channel config without mutating shared defaults).

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +28
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5268",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "https://localhost:7165;http://localhost:5268",
"environmentVariables": {
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

launchUrl is set to weatherforecast, but the API doesn't map a /weatherforecast endpoint in Program.cs (only /api/*). This will open a 404 on launch; update launchUrl to something valid (e.g., api/health) or remove it.

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +13 to +18
- `/home/runner/work/Gateways/Gateways/src/IoTSharp.Gateways.Domain`:领域模型与统一驱动接口
- `/home/runner/work/Gateways/Gateways/src/IoTSharp.Gateways.Application`:配置服务、运行编排、转换服务
- `/home/runner/work/Gateways/Gateways/src/IoTSharp.Gateways.Infrastructure`:SQLite 仓储、驱动适配器、HTTP/MQTT 上传
- `/home/runner/work/Gateways/Gateways/src/IoTSharp.Gateways.Api`:ASP.NET Core Web API
- `/home/runner/work/Gateways/Gateways/src/IoTSharp.Gateways.Worker`:后台采集执行 Worker
- `/home/runner/work/Gateways/Gateways/src/gateway-web`:Vue 3 管理前端
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README hard-codes GitHub Actions runner absolute paths (e.g. /home/runner/work/Gateways/Gateways/...), which won't work for local checkouts. Use relative paths (e.g. src/IoTSharp.Gateways.Api/...) or repo-root based instructions instead.

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +14
builder.Services.Configure<Microsoft.Extensions.Hosting.HostOptions>(options =>
{
options.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
});
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BackgroundServiceExceptionBehavior is set to Ignore, which can leave the process running even when hosted services fail unexpectedly, making failures harder to detect operationally. Prefer StopHost (default) or make this configurable per environment if you need to tolerate certain failures.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +10
async function request<T>(path: string, init?: RequestInit): Promise<T> {
const response = await fetch(`${apiBaseUrl}${path}`, {
headers: {
'Content-Type': 'application/json',
...(init?.headers ?? {}),
},
...init,
})
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

request() spreads ...init after building the headers object, so if a caller passes init.headers, it will overwrite the merged headers and drop the default Content-Type: application/json (and any other defaults). Reorder the spread so init is applied first, then build/merge headers last.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +12
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vite-plugin-vue-devtools is currently enabled unconditionally, which can impact production builds (bundle size / devtools exposure). Consider enabling it only for command === 'serve' / non-production mode.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +18
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy => policy.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
});
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API enables a default CORS policy with AllowAnyOrigin/AnyHeader/AnyMethod. If this host is exposed beyond local development, this is a security risk. Consider restricting origins via configuration (and/or only enabling permissive CORS in Development).

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +4
@IoTSharp.Gateways.Api_HostAddress = http://localhost:5268

GET {{IoTSharp.Gateways.Api_HostAddress}}/weatherforecast/
Accept: application/json
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sample request targets /weatherforecast/, but this project currently exposes health/config endpoints under /api/* (e.g. /api/health). Updating this file will prevent confusion when testing the API.

Copilot uses AI. Check for mistakes.
Comment on lines +26 to +46
var tasks = (await repository.GetPollingTasksAsync(stoppingToken)).Where(task => task.Enabled).ToArray();
var now = DateTimeOffset.UtcNow;
foreach (var task in tasks)
{
if (_nextRuns.TryGetValue(task.Id, out var nextRun) && nextRun > now)
{
continue;
}

var report = await runtimeService.ExecutePollingTaskAsync(task.Id, stoppingToken);
_logger.LogInformation("Executed polling task {TaskName} with {SuccessCount} successes and {FailureCount} failures.", report.TaskName, report.SuccessCount, report.FailureCount);
_nextRuns[task.Id] = now.AddSeconds(Math.Max(task.IntervalSeconds, 1));
}
}
catch (Exception exception)
{
_logger.LogError(exception, "Gateway polling iteration failed.");
}

await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The polling loop sleeps for a fixed 5 seconds, so tasks with IntervalSeconds < 5 cannot run at their configured cadence. Also, _nextRuns never removes entries for tasks that were deleted/disabled, so it can grow unbounded over time. Consider computing the next delay based on the soonest scheduled run and pruning _nextRuns for tasks not returned by the repository.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants