signalk-server
Version:
An implementation of a [Signal K](http://signalk.org) server for boats.
75 lines (70 loc) • 31.8 kB
HTML
<html class="default" lang="en" data-base="../../../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>Deltas | Signal K</title><meta name="description" content="Documentation for Signal K"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../../../assets/style.css?cache=1783009712609"/><link rel="stylesheet" href="../../../assets/highlight.css?cache=1783009712609"/><script defer src="../../../assets/main.js?cache=1783009712609"></script><script async src="../../../assets/icons.js?cache=1783009712609" id="tsd-icons-script"></script><script async src="../../../assets/search.js?cache=1783009712609" id="tsd-search-script"></script><script async src="../../../assets/navigation.js?cache=1783009712609" id="tsd-nav-script"></script><script async src="../../../assets/hierarchy.js?cache=1783009712609" id="tsd-hierarchy-script"></script><link rel="stylesheet" href="../../../assets/theme.css"/><script>if(window.self!==window.top){document.documentElement.classList.add('embedded')}</script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../../../index.html" class="title"><img class="title-logo" src="../../../assets/logo.svg" alt="Signal K"/><svg class="title-home-icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-label="Documentation home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg></a><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../../../assets/icons.svg#icon-search"></use></svg><span class="visible@s">Search</span></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><div id="tsd-toolbar-links"><a href="https://discord.gg/uuZrwz4dCS" target="_blank" rel="noopener" class="toolbar-icon visible@s" aria-label="Discord"><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M524.5 69.8a1.5 1.5 0 0 0 -.8-.7A485.1 485.1 0 0 0 404.1 32a1.8 1.8 0 0 0 -1.9 .9 337.5 337.5 0 0 0 -14.9 30.6 447.8 447.8 0 0 0 -134.4 0 309.5 309.5 0 0 0 -15.1-30.6 1.9 1.9 0 0 0 -1.9-.9A483.7 483.7 0 0 0 116.1 69.1a1.7 1.7 0 0 0 -.8 .7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 0 0 .8 1.4A487.7 487.7 0 0 0 176 479.9a1.9 1.9 0 0 0 2.1-.7A348.2 348.2 0 0 0 208.1 430.4a1.9 1.9 0 0 0 -1-2.6 321.2 321.2 0 0 1 -45.9-21.9 1.9 1.9 0 0 1 -.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8 0 0 1 1.9-.3c96.2 43.9 200.4 43.9 295.5 0a1.8 1.8 0 0 1 1.9 .2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9 0 0 1 -.2 3.1 301.4 301.4 0 0 1 -45.9 21.8 1.9 1.9 0 0 0 -1 2.6 391.1 391.1 0 0 0 30 48.8 1.9 1.9 0 0 0 2.1 .7A486 486 0 0 0 610.7 405.7a1.9 1.9 0 0 0 .8-1.4C623.7 277.6 590.9 167.5 524.5 69.8zM222.5 337.6c-29 0-52.8-26.6-52.8-59.2S193.1 219.1 222.5 219.1c29.7 0 53.3 26.8 52.8 59.2C275.3 311 251.9 337.6 222.5 337.6zm195.4 0c-29 0-52.8-26.6-52.8-59.2S388.4 219.1 417.9 219.1c29.7 0 53.3 26.8 52.8 59.2C470.7 311 447.5 337.6 417.9 337.6z"></path></svg></a><a href="https://github.com/SignalK/signalk-server" target="_blank" rel="noopener" class="toolbar-icon visible@s" aria-label="Discord"><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg></a><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../../../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../../../Developing.html">Developing</a></li><li><a href="../../Plugins.html">Plugins</a></li><li><a href="../WASM_Plugins.html">WASM Plugins</a></li><li><a href="" aria-current="page">Deltas</a></li></ul></div><div class="tsd-panel tsd-typography"><h1 id="working-with-signal-k-deltas" class="tsd-anchor-link">Working with Signal K Deltas<a href="#working-with-signal-k-deltas" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h1>
<p>WASM plugins can both <strong>emit</strong> and <strong>receive</strong> Signal K deltas. This page covers both directions.</p>
<h2 id="emitting-deltas" class="tsd-anchor-link">Emitting Deltas<a href="#emitting-deltas" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<p>Use the <code>emit()</code> function to send delta messages to the Signal K server:</p>
<pre><code class="typescript"><span class="hl-1">import</span><span class="hl-0"> {</span><br/><span class="hl-0"> emit,</span><br/><span class="hl-0"> createSimpleDelta,</span><br/><span class="hl-0"> SK_VERSION_V1,</span><br/><span class="hl-0"> SK_VERSION_V2</span><br/><span class="hl-0">} </span><span class="hl-1">from</span><span class="hl-0"> </span><span class="hl-4">'@signalk/assemblyscript-plugin-sdk/assembly'</span><br/><br/><span class="hl-6">// Emit a v1 delta (default - for regular navigation data)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">tempDelta</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">createSimpleDelta</span><span class="hl-0">(</span><span class="hl-4">'environment.outside.temperature'</span><span class="hl-0">, </span><span class="hl-4">'288.15'</span><span class="hl-0">)</span><br/><span class="hl-7">emit</span><span class="hl-0">(tempDelta)</span><br/><br/><span class="hl-6">// Emit a v2 delta (for Course API and v2-specific paths)</span><br/><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">courseDelta</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">createSimpleDelta</span><span class="hl-0">(</span><br/><span class="hl-0"> </span><span class="hl-4">'navigation.course.nextPoint'</span><span class="hl-0">,</span><br/><span class="hl-0"> positionJson</span><br/><span class="hl-0">)</span><br/><span class="hl-7">emit</span><span class="hl-0">(courseDelta, </span><span class="hl-2">SK_VERSION_V2</span><span class="hl-0">)</span>
</code><button type="button">Copy</button></pre>
<p><strong>Note:</strong> Plugins should NOT include <code>source</code> or <code>timestamp</code> in emitted deltas. The server automatically:</p>
<ul>
<li>Sets <code>$source</code> to the plugin ID</li>
<li>Fills in <code>timestamp</code> with the current time</li>
</ul>
<h3 id="signal-k-v1-vs-v2-deltas" class="tsd-anchor-link">Signal K v1 vs v2 Deltas<a href="#signal-k-v1-vs-v2-deltas" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h3>
<p>The <code>emit()</code> function accepts an optional second parameter to specify the Signal K version:</p>
<table>
<thead>
<tr>
<th>Version</th>
<th>Constant</th>
<th>Use Case</th>
</tr>
</thead>
<tbody>
<tr>
<td>v1 (default)</td>
<td><code>SK_VERSION_V1</code></td>
<td>Regular navigation data: <code>navigation.*</code>, <code>environment.*</code>, <code>electrical.*</code>, etc.</td>
</tr>
<tr>
<td>v2</td>
<td><code>SK_VERSION_V2</code></td>
<td>Course API paths and v2-specific data that should not be mixed into the v1 full data model</td>
</tr>
</tbody>
</table>
<p><strong>Why does this matter?</strong></p>
<ul>
<li><strong>v1 deltas</strong> update the full Signal K data model and are available via the REST API and WebSocket subscriptions</li>
<li><strong>v2 deltas</strong> are emitted as events for v2 API subscribers without mixing into the v1 data model</li>
</ul>
<p>Most plugins should use v1 (the default). Only use v2 when emitting Course API data or other v2-specific paths.</p>
<p>This mirrors the TypeScript plugin API where <code>handleMessage()</code> accepts an optional <code>skVersion</code> parameter.</p>
<hr>
<h2 id="receiving-deltas" class="tsd-anchor-link">Receiving Deltas<a href="#receiving-deltas" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<p>WASM plugins can subscribe to receive Signal K deltas, enabling them to react to navigation data changes, course updates, sensor readings, and other vessel data in real-time.</p>
<h2 id="implementing-a-delta-handler" class="tsd-anchor-link">Implementing a Delta Handler<a href="#implementing-a-delta-handler" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<p>Export a <code>delta_handler()</code> function to receive deltas:</p>
<pre><code class="typescript"><span class="hl-6">// assembly/index.ts</span><br/><br/><span class="hl-6">// Plugin state</span><br/><span class="hl-1">let</span><span class="hl-0"> vesselLat</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">f64</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">0.0</span><br/><span class="hl-1">let</span><span class="hl-0"> vesselLon</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">f64</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">0.0</span><br/><span class="hl-1">let</span><span class="hl-0"> hasPosition</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">bool</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">false</span><br/><br/><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">delta_handler</span><span class="hl-0">(</span><span class="hl-5">deltaJson</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0">)</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">void</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-6">// Check for position updates</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (deltaJson.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"path":"navigation.position"'</span><span class="hl-0">) </span><span class="hl-1">>=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">lat</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(deltaJson, </span><span class="hl-4">'latitude'</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">lon</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(deltaJson, </span><span class="hl-4">'longitude'</span><span class="hl-0">)</span><br/><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (lat </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">0.0</span><span class="hl-0"> </span><span class="hl-1">||</span><span class="hl-0"> lon </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">0.0</span><span class="hl-0">) {</span><br/><span class="hl-0"> vesselLat </span><span class="hl-1">=</span><span class="hl-0"> lat</span><br/><span class="hl-0"> vesselLon </span><span class="hl-1">=</span><span class="hl-0"> lon</span><br/><span class="hl-0"> hasPosition </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">true</span><br/><span class="hl-0"> </span><span class="hl-7">debug</span><span class="hl-0">(</span><span class="hl-4">'Position updated: '</span><span class="hl-0"> </span><span class="hl-1">+</span><span class="hl-0"> lat.</span><span class="hl-7">toString</span><span class="hl-0">() </span><span class="hl-1">+</span><span class="hl-0"> </span><span class="hl-4">', '</span><span class="hl-0"> </span><span class="hl-1">+</span><span class="hl-0"> lon.</span><span class="hl-7">toString</span><span class="hl-0">())</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-6">// Check for course nextPoint</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (deltaJson.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"path":"navigation.course.nextPoint"'</span><span class="hl-0">) </span><span class="hl-1">>=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-6">// Extract destination coordinates and perform calculations</span><br/><span class="hl-0"> </span><span class="hl-6">// ...</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-6">// Check for speedOverGround</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (deltaJson.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"navigation.speedOverGround"'</span><span class="hl-0">) </span><span class="hl-1">>=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">speed</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(deltaJson, </span><span class="hl-4">'value'</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-6">// Process speed data</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span><br/><br/><span class="hl-6">// Helper function to parse float from JSON</span><br/><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(</span><span class="hl-5">json</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0">, </span><span class="hl-5">key</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0">)</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-5">f64</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">searchKey</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-4">'"'</span><span class="hl-0"> </span><span class="hl-1">+</span><span class="hl-0"> key </span><span class="hl-1">+</span><span class="hl-0"> </span><span class="hl-4">'":'</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">match</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> json.</span><span class="hl-7">indexOf</span><span class="hl-0">(searchKey)</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (match </span><span class="hl-1"><</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-2">0.0</span><br/><br/><span class="hl-0"> </span><span class="hl-1">let</span><span class="hl-0"> start </span><span class="hl-1">=</span><span class="hl-0"> match </span><span class="hl-1">+</span><span class="hl-0"> searchKey.</span><span class="hl-2">length</span><br/><span class="hl-0"> </span><span class="hl-1">while</span><span class="hl-0"> (</span><br/><span class="hl-0"> start </span><span class="hl-1"><</span><span class="hl-0"> json.</span><span class="hl-2">length</span><span class="hl-0"> </span><span class="hl-1">&&</span><br/><span class="hl-0"> (json.</span><span class="hl-7">charCodeAt</span><span class="hl-0">(start) </span><span class="hl-1">==</span><span class="hl-0"> </span><span class="hl-2">32</span><span class="hl-0"> </span><span class="hl-1">||</span><span class="hl-0"> json.</span><span class="hl-7">charCodeAt</span><span class="hl-0">(start) </span><span class="hl-1">==</span><span class="hl-0"> </span><span class="hl-2">9</span><span class="hl-0">)</span><br/><span class="hl-0"> ) {</span><br/><span class="hl-0"> start</span><span class="hl-1">++</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-1">let</span><span class="hl-0"> end </span><span class="hl-1">=</span><span class="hl-0"> start</span><br/><span class="hl-0"> </span><span class="hl-1">while</span><span class="hl-0"> (end </span><span class="hl-1"><</span><span class="hl-0"> json.</span><span class="hl-2">length</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">c</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> json.</span><span class="hl-7">charCodeAt</span><span class="hl-0">(end)</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (c </span><span class="hl-1">==</span><span class="hl-0"> </span><span class="hl-2">44</span><span class="hl-0"> </span><span class="hl-1">||</span><span class="hl-0"> c </span><span class="hl-1">==</span><span class="hl-0"> </span><span class="hl-2">125</span><span class="hl-0"> </span><span class="hl-1">||</span><span class="hl-0"> c </span><span class="hl-1">==</span><span class="hl-0"> </span><span class="hl-2">93</span><span class="hl-0">) </span><span class="hl-1">break</span><span class="hl-0"> </span><span class="hl-6">// comma, }, ]</span><br/><span class="hl-0"> end</span><span class="hl-1">++</span><br/><span class="hl-0"> }</span><br/><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">numStr</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> json.</span><span class="hl-7">substring</span><span class="hl-0">(start, end).</span><span class="hl-7">trim</span><span class="hl-0">()</span><br/><span class="hl-0"> </span><span class="hl-1">return</span><span class="hl-0"> </span><span class="hl-7">parseFloat</span><span class="hl-0">(numStr)</span><br/><span class="hl-0">}</span>
</code><button type="button">Copy</button></pre>
<h2 id="received-delta-json-format" class="tsd-anchor-link">Received Delta JSON Format<a href="#received-delta-json-format" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<p>Deltas received by <code>delta_handler()</code> include <code>$source</code> and <code>timestamp</code> (added by the server):</p>
<pre><code class="json"><span class="hl-0">{</span><br/><span class="hl-0"> </span><span class="hl-3">"context"</span><span class="hl-0">: </span><span class="hl-4">"vessels.self"</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">"updates"</span><span class="hl-0">: [</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-3">"$source"</span><span class="hl-0">: </span><span class="hl-4">"n2k-on-ve.can-socket.43"</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">"timestamp"</span><span class="hl-0">: </span><span class="hl-4">"2024-01-15T12:30:00.000Z"</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">"values"</span><span class="hl-0">: [</span><br/><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-3">"path"</span><span class="hl-0">: </span><span class="hl-4">"navigation.position"</span><span class="hl-0">,</span><br/><span class="hl-0"> </span><span class="hl-3">"value"</span><span class="hl-0">: { </span><span class="hl-3">"latitude"</span><span class="hl-0">: </span><span class="hl-2">-17.68</span><span class="hl-0">, </span><span class="hl-3">"longitude"</span><span class="hl-0">: </span><span class="hl-2">177.39</span><span class="hl-0"> }</span><br/><span class="hl-0"> },</span><br/><span class="hl-0"> { </span><span class="hl-3">"path"</span><span class="hl-0">: </span><span class="hl-4">"navigation.speedOverGround"</span><span class="hl-0">, </span><span class="hl-3">"value"</span><span class="hl-0">: </span><span class="hl-2">5.2</span><span class="hl-0"> }</span><br/><span class="hl-0"> ]</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> ]</span><br/><span class="hl-0">}</span>
</code><button type="button">Copy</button></pre>
<h2 id="common-use-cases" class="tsd-anchor-link">Common Use Cases<a href="#common-use-cases" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<ol>
<li><strong>Course Calculations</strong> - React to <code>navigation.course.nextPoint</code> and <code>navigation.position</code> to calculate bearing, distance, XTE</li>
<li><strong>Anchor Watch</strong> - Monitor <code>navigation.position</code> and compare to anchor position</li>
<li><strong>Speed Alerts</strong> - Watch <code>navigation.speedOverGround</code> for threshold breaches</li>
<li><strong>Environment Monitoring</strong> - Track <code>environment.wind.*</code>, <code>environment.water.temperature</code>, etc.</li>
</ol>
<h2 id="detecting-cleared-values" class="tsd-anchor-link">Detecting Cleared Values<a href="#detecting-cleared-values" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<p>When values are cleared (e.g., destination removed), the server sends <code>null</code> values:</p>
<pre><code class="typescript"><span class="hl-1">export</span><span class="hl-0"> </span><span class="hl-1">function</span><span class="hl-0"> </span><span class="hl-7">delta_handler</span><span class="hl-0">(</span><span class="hl-5">deltaJson</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">string</span><span class="hl-0">)</span><span class="hl-1">:</span><span class="hl-0"> </span><span class="hl-2">void</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (deltaJson.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"path":"navigation.course.nextPoint"'</span><span class="hl-0">) </span><span class="hl-1">>=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-6">// Try to extract position first</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">lat</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(deltaJson, </span><span class="hl-4">'latitude'</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">lon</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-7">parseFloat64FromJson</span><span class="hl-0">(deltaJson, </span><span class="hl-4">'longitude'</span><span class="hl-0">)</span><br/><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (lat </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">0.0</span><span class="hl-0"> </span><span class="hl-1">||</span><span class="hl-0"> lon </span><span class="hl-1">!==</span><span class="hl-0"> </span><span class="hl-2">0.0</span><span class="hl-0">) {</span><br/><span class="hl-0"> </span><span class="hl-6">// Valid position - update state</span><br/><span class="hl-0"> nextPointLat </span><span class="hl-1">=</span><span class="hl-0"> lat</span><br/><span class="hl-0"> nextPointLon </span><span class="hl-1">=</span><span class="hl-0"> lon</span><br/><span class="hl-0"> hasDestination </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">true</span><br/><span class="hl-0"> } </span><span class="hl-1">else</span><span class="hl-0"> {</span><br/><span class="hl-0"> </span><span class="hl-6">// Check if this is a null/clear operation</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">pathIdx</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> deltaJson.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"path":"navigation.course.nextPoint"'</span><span class="hl-0">)</span><br/><span class="hl-0"> </span><span class="hl-1">const</span><span class="hl-0"> </span><span class="hl-2">checkRange</span><span class="hl-0"> </span><span class="hl-1">=</span><span class="hl-0"> deltaJson.</span><span class="hl-7">substring</span><span class="hl-0">(</span><br/><span class="hl-0"> pathIdx,</span><br/><span class="hl-0"> Math.</span><span class="hl-7">min</span><span class="hl-0">(pathIdx </span><span class="hl-1">+</span><span class="hl-0"> </span><span class="hl-2">100</span><span class="hl-0">, deltaJson.</span><span class="hl-2">length</span><span class="hl-0">) </span><span class="hl-1">as</span><span class="hl-0"> </span><span class="hl-5">i32</span><br/><span class="hl-0"> )</span><br/><span class="hl-0"> </span><span class="hl-1">if</span><span class="hl-0"> (checkRange.</span><span class="hl-7">indexOf</span><span class="hl-0">(</span><span class="hl-4">'"value":null'</span><span class="hl-0">) </span><span class="hl-1">>=</span><span class="hl-0"> </span><span class="hl-2">0</span><span class="hl-0">) {</span><br/><span class="hl-0"> hasDestination </span><span class="hl-1">=</span><span class="hl-0"> </span><span class="hl-2">false</span><br/><span class="hl-0"> </span><span class="hl-7">debug</span><span class="hl-0">(</span><span class="hl-4">'Destination cleared'</span><span class="hl-0">)</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> }</span><br/><span class="hl-0"> }</span><br/><span class="hl-0">}</span>
</code><button type="button">Copy</button></pre>
<h2 id="performance-considerations" class="tsd-anchor-link">Performance Considerations<a href="#performance-considerations" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../../../assets/icons.svg#icon-anchor"></use></svg></a></h2>
<ul>
<li><strong>Filter Early</strong> - Check for relevant paths before parsing to minimize processing</li>
<li><strong>State Caching</strong> - Store parsed values in global variables rather than re-parsing</li>
<li><strong>Debouncing</strong> - High-frequency data (GPS at 10Hz) may benefit from debouncing calculations</li>
</ul>
</div></div><div class="col-sidebar"><div class="page-menu"><details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../../../assets/icons.svg#icon-chevronDown"></use></svg><h3>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#emitting-deltas"><span>Emitting <wbr/>Deltas</span></a><ul><li><a href="#signal-k-v1-vs-v2-deltas"><span>Signal <wbr/>K v1 vs v2 <wbr/>Deltas</span></a></li></ul><a href="#receiving-deltas"><span>Receiving <wbr/>Deltas</span></a><a href="#implementing-a-delta-handler"><span>Implementing a <wbr/>Delta <wbr/>Handler</span></a><a href="#received-delta-json-format"><span>Received <wbr/>Delta <wbr/>JSON <wbr/>Format</span></a><a href="#common-use-cases"><span>Common <wbr/>Use <wbr/>Cases</span></a><a href="#detecting-cleared-values"><span>Detecting <wbr/>Cleared <wbr/>Values</span></a><a href="#performance-considerations"><span>Performance <wbr/>Considerations</span></a></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="../../../modules.html">Signal K</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>