Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions data/eventFirmware.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"version": 1,
"generatedAt": "2026-06-23T00:00:00Z",
"source": "bundled",
"editions": [
{
"edition": "HAMVENTION",
"displayName": "Hamvention",
"welcomeMessage": "Welcome to Hamvention! 🍖📻",
"eventStart": "2026-05-15",
"eventEnd": "2026-05-17",
"timeZone": "America/New_York",
"location": "Xenia, Ohio, USA",
"iconUrl": "https://api.meshtastic.org/resource/eventFirmware/hamvention.png",
"accentColor": "#BF1E2E",
"links": [
{ "label": "Event Website", "url": "https://hamvention.org" }
]
},
{
"edition": "OPEN_SAUCE",
"displayName": "Open Sauce",
"welcomeMessage": "Welcome to Open Sauce! 🔧",
"eventStart": "2026-07-17",
"eventEnd": "2026-07-19",
"timeZone": "America/Los_Angeles",
"location": "San Mateo, California, USA",
"iconUrl": null,
"accentColor": "#E94F1D",
"links": [
{ "label": "Event Website", "url": "https://opensauce.com" }
]
},
{
"edition": "DEFCON",
"displayName": "DEFCON",
"welcomeMessage": "Welcome to DEFCON! 💀",
"eventStart": "2026-08-06",
"eventEnd": "2026-08-09",
"timeZone": "America/Los_Angeles",
"location": "Las Vegas, Nevada, USA",
"iconUrl": null,
"accentColor": "#0D294A",
"links": [
{ "label": "Event Website", "url": "https://defcon.org" }
]
},
{
"edition": "BURNING_MAN",
"displayName": "Burning Man",
"welcomeMessage": "Welcome to Burning Man! 🔥",
"eventStart": "2026-08-30",
"eventEnd": "2026-09-07",
"timeZone": "America/Los_Angeles",
"location": "Black Rock City, Nevada, USA",
"iconUrl": null,
"accentColor": "#EC8819",
"links": [
{ "label": "Event Website", "url": "https://burningman.org" }
]
}
]
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import { RegisterMqttClient } from "./lib/index.js";
import {
DeviceLinksRoutes,
EventFirmwareIconRoutes,
EventFirmwareRoutes,
FirmwareRoutes,
GithubRoutes,
MqttRoutes,
Expand Down Expand Up @@ -72,7 +74,7 @@
router.service(GatewayService, new Gateway());
},
connect: true,
// @ts-ignore

Check warning on line 77 in src/index.ts

View workflow job for this annotation

GitHub Actions / quality

lint/suspicious/noTsIgnore

Unsafe use of the @ts-ignore directive found in this comment.
})(req, res, next);
});

Expand All @@ -83,7 +85,9 @@
GithubRoutes();
ResourceRoutes();
DeviceLinksRoutes();
EventFirmwareRoutes();
EventFirmwareIconRoutes();
UpdaterRoutes();
MqttRoutes();

app.listen(Number.parseInt(process.env.PORT ?? "4000"));

Check notice on line 93 in src/index.ts

View workflow job for this annotation

GitHub Actions / quality

lint/correctness/useParseIntRadix

Missing radix parameter
45 changes: 45 additions & 0 deletions src/lib/eventFirmware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { readFileSync } from "node:fs";

// Event-firmware display metadata. Authored to the contract in
// meshtastic/Meshtastic-Android#5920 (schemas/event_firmware.schema.json). The committed file is
// already in the response envelope shape, so unlike deviceLinks there is nothing to transform —
// we parse and serve it verbatim. This repo is the source of truth the app syncs from.
// The path resolves the same in dev (src/lib) and prod (dist/lib), both two levels below the root.
const DATA_PATH = new URL("../../data/eventFirmware.json", import.meta.url);

export interface EventFirmwareLink {
label: string;
url: string;
}

export interface EventFirmwareEdition {
edition: string; // FirmwareEdition proto enum name, e.g. "HAMVENTION"
displayName: string;
welcomeMessage: string;
eventStart?: string | null;
eventEnd?: string | null;
timeZone?: string | null;
location?: string | null;
iconUrl?: string | null;
accentColor?: string | null;
links?: EventFirmwareLink[];
}

export interface EventFirmwareResponse {
version: number;
generatedAt?: string;
source?: string;
editions: EventFirmwareEdition[];
}

// Parse once per process — the file only changes via a committed edit + redeploy.
let cached: EventFirmwareResponse | null = null;

export const getEventFirmware = (): EventFirmwareResponse => {
if (!cached) {
cached = JSON.parse(
readFileSync(DATA_PATH, "utf8"),
) as EventFirmwareResponse;
}
return cached;
};
12 changes: 12 additions & 0 deletions src/routes/eventFirmware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { app } from "../index.js";
import { getEventFirmware } from "../lib/eventFirmware.js";

export const EventFirmwareRoutes = () =>
app.get("resource/eventFirmware", (_req, res) => {
try {
res.json(getEventFirmware());
} catch (err) {
console.error("eventFirmware", err);
res.sendStatus(502);
}
});
24 changes: 24 additions & 0 deletions src/routes/eventFirmwareIcon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { readFileSync } from "node:fs";
import { app } from "../index.js";

// Hamvention is the only event edition with bundled art today (the others' iconUrl is null).
// Served under resource/ alongside the metadata, mirroring how data/ files map to resource/* routes.
// ponytail: one fixed route for the one icon we host; generalize to a :slug param when more editions ship art.
const ICON_PATH = new URL(
"../../static/eventFirmware/hamvention.png",
import.meta.url,
);

let icon: Buffer | null = null;

export const EventFirmwareIconRoutes = () =>
app.get("resource/eventFirmware/hamvention.png", (_req, res) => {
try {
if (!icon) icon = readFileSync(ICON_PATH);
res.setHeader("Content-Type", "image/png");
res.send(icon);
} catch (err) {
console.error("eventFirmwareIcon", err);
res.sendStatus(404);
}
});
2 changes: 2 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { DeviceLinksRoutes } from "./deviceLinks.js";
export { EventFirmwareRoutes } from "./eventFirmware.js";
export { EventFirmwareIconRoutes } from "./eventFirmwareIcon.js";
export { FirmwareRoutes } from "./firmware.js";
export { GithubRoutes } from "./github.js";
export { MqttRoutes } from "./mqtt.js";
Expand Down
Binary file added static/eventFirmware/hamvention.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading