Skip to content

Server-side API

The resource’s server script keeps a live link to the radio server. It’s on by default and needs nothing beyond the normal setup: it uses meridian_secret to prove it belongs to your radio system (the secret itself is never sent), and the address of meridian_url with /game added (wss://example/ws becomes wss://example/ws/game).

set meridian_server_api "false" # turn the link off (radios keep working, but the server stops checking their signal)
set meridian_game_url "wss://example.com/ws/game" # only if the address can't be worked out from meridian_url

The server console shows linked to the radio server once it’s up. If it can’t link, it says why (usually a secret that doesn’t match the radio server’s) and keeps retrying.

if exports.meridian:isLinked() then
for _, unit in ipairs(exports.meridian:getUnits()) do
print(unit.alias, unit.talkgroupId, unit.player)
end
end
Export Returns
isLinked() Whether the link to the radio server is up
getTalkgroups() Every talkgroup: { id, name, alias }
getUnits() Every connected radio (see below)
getUnit(unitId) One radio, or nil
getUnitByPlayer(playerId) A player’s radio if it’s connected, or nil
getUnitIdForPlayer(playerId) A player’s unit ID, even if their radio is off (it’s fixed per player)
getCalls() Calls in progress: { callId, talkgroupId, unitId, alias, emergency, startedAt, fromConsole, player }
getEmergencies() Active emergencies: { unitId, alias, talkgroupId, acknowledgedBy, since, player }

A radio (unit) is { unitId, alias, agencies, talkgroupId, siteId, bars, inhibited, player }. player is the player’s server ID, or nil for a radio that isn’t a player on this server. Times are milliseconds since the epoch. While the link is down these return the last known state; check isLinked().

These are local server events.

Event Arguments
meridian:linkChanged linked
meridian:unitConnected unit
meridian:unitDisconnected unit
meridian:unitTalkgroupChanged unit, previousTalkgroupId
meridian:unitInhibited unit, inhibited
meridian:callStarted call
meridian:callEnded call
meridian:emergencyRaised emergency
meridian:emergencyAcknowledged emergency
meridian:emergencyCleared emergency

An emergency that moves to another talkgroup is cleared, then raised again. After the link drops and comes back, events describe what changed in the meantime.

-- Panic blip for everyone on duty when an emergency is raised
AddEventHandler("meridian:emergencyRaised", function(e)
if not e.player then return end
local coords = GetEntityCoords(GetPlayerPed(e.player))
TriggerClientEvent("my-cad:panicBlip", -1, e.alias, coords)
end)
Export Effect
acknowledgeEmergency(unitId, by?, cb?) Acknowledge a radio’s emergency; radios show who acknowledged it
clearEmergency(unitId, by?, cb?) Clear a radio’s emergency
raiseEmergency(unitId, talkgroupId?, by?, cb?) Raise an emergency for a radio (a panic button in your script), on talkgroupId or its selected talkgroup
setInhibited(unitId, inhibited, by?, cb?) Disable or re-enable a radio
setTalkgroup(unitId, talkgroupId, by?, cb?) Move a radio to a talkgroup in its codeplug
alertUnits(unitIds, tone, by?, cb?) Play an alert tone on a list of radios
alertTalkgroup(talkgroupId, tone, by?, cb?) Play an alert tone on every radio selected to a talkgroup

Tones are "alert" (three long beeps), "priority" (a hi-lo warble) and "page" (two short beeps).

by is who took the action, for example the CAD user’s name (up to 48 characters). It’s shown on radios for acknowledgements and recorded in the audit log; without it the action shows as “Game server”. The audit log also records which resource called the export.

Each action returns true if it was sent, or false if the arguments are invalid or the link is down. To learn the outcome, pass a callback: it’s called with ok, error, message, where error is one of unit_offline, no_emergency, no_talkgroup, no_permission, unknown_talkgroup, inhibited, out_of_range, bad_request, rate_limited, not_linked or timeout.

local unitId = exports.meridian:getUnitIdForPlayer(source)
exports.meridian:setTalkgroup(unitId, 501, "CAD: " .. dispatcherName, function(ok, err)
if not ok then print("couldn't move the radio: " .. err) end
end)
exports.meridian:alertTalkgroup(101, "priority", "Dispatch")

These exports are only available to server scripts. Players can’t reach them; if you expose them through your own net events or commands, check the player is allowed to use them first.