[{"data":1,"prerenderedAt":1762},["ShallowReactive",2],{"docs:/docs/high-level-sdks/iot":3},{"id":4,"title":5,"body":6,"description":1755,"extension":1756,"meta":1757,"navigation":275,"path":1758,"seo":1759,"stem":1760,"__hash__":1761},"docs/docs/high-level-sdks/iot.md","IoT SDK",{"type":7,"value":8,"toc":1741},"minimark",[9,14,18,23,40,45,70,74,111,168,172,204,227,231,1163,1167,1170,1175,1356,1444,1448,1547,1550,1648,1652,1737],[10,11,13],"h1",{"id":12},"nolagiot","@nolag/iot",[15,16,17],"p",{},"IoT device telemetry and command dispatch with acknowledgment tracking.",[19,20,22],"h2",{"id":21},"overview","Overview",[15,24,25,26,30,31,34,35,39],{},"Connect IoT devices and controllers over real-time channels. Devices push telemetry (sensor readings, status updates, or any structured measurement) while controllers dispatch commands with Promise-based acknowledgment tracking and configurable timeouts. Two roles participate in a device group: ",[27,28,29],"strong",{},"devices"," report data and acknowledge commands, and ",[27,32,33],{},"controllers"," monitor telemetry streams and issue commands. A single client can act as both. Groups organise devices by fleet, physical location, or function. Your app owns one core NoLag client and injects it into ",[36,37,38],"code",{},"NoLagIoT","; the wrapper attaches its behaviour to that connection.",[41,42,44],"h3",{"id":43},"key-features","Key Features",[46,47,48,52,55,58,61,64,67],"ul",{},[49,50,51],"li",{},"Real-time telemetry broadcast from devices to all group subscribers",[49,53,54],{},"Promise-based command dispatch with configurable acknowledgment timeout",[49,56,57],{},"Ephemeral telemetry for high-frequency data without storage overhead",[49,59,60],{},"Ephemeral commands with fire-and-forget dispatch and ack tracking",[49,62,63],{},"Ephemeral acknowledgment channel for command response tracking",[49,65,66],{},"Device online/offline presence via lobby",[49,68,69],{},"Multiple groups per connection; join by zone, building floor, vehicle type, etc.",[19,71,73],{"id":72},"how-it-works","How It Works",[15,75,76,78,79,82,83,86,87,90,91,94,95,98,99,102,103,106,107,110],{},[36,77,38],{}," attaches to an injected ",[36,80,81],{},"@nolag/js-sdk"," client and manages a lobby that reflects device presence. Calling ",[36,84,85],{},"joinGroup(name)"," returns a ",[36,88,89],{},"DeviceGroup"," that subscribes to three topics: ",[36,92,93],{},"telemetry"," for ephemeral sensor readings, ",[36,96,97],{},"commands"," for ephemeral command payloads, and ",[36,100,101],{},"_cmd_ack"," for ephemeral acknowledgment messages. All topics are ephemeral (no server-side retention) to handle high-frequency telemetry without storage overhead. When a controller calls ",[36,104,105],{},"sendCommand()"," the SDK stores a pending Promise keyed on the command ID; when the target device calls ",[36,108,109],{},"ackCommand()"," the matching Promise resolves or rejects based on the reported status. The app owns the socket lifecycle; the wrapper never opens or closes it.",[112,113,114,130],"table",{},[115,116,117],"thead",{},[118,119,120,124,127],"tr",{},[121,122,123],"th",{},"Topic",[121,125,126],{},"Purpose",[121,128,129],{},"Replay",[131,132,133,146,157],"tbody",{},[118,134,135,140,143],{},[136,137,138],"td",{},[36,139,93],{},[136,141,142],{},"Sensor readings and device status updates",[136,144,145],{},"Ephemeral",[118,147,148,152,155],{},[136,149,150],{},[36,151,97],{},[136,153,154],{},"Commands dispatched to devices",[136,156,145],{},[118,158,159,163,166],{},[136,160,161],{},[36,162,101],{},[136,164,165],{},"Command acknowledgment messages",[136,167,145],{},[19,169,171],{"id":170},"installation","Installation",[173,174,175],"code-tabs",{},[176,177,183],"pre",{"className":178,"code":179,"filename":180,"language":181,"meta":182,"style":182},"language-bash shiki shiki-themes github-light github-dark","npm install @nolag/iot @nolag/js-sdk\n","Terminal","bash","",[36,184,185],{"__ignoreMap":182},[186,187,190,194,198,201],"span",{"class":188,"line":189},"line",1,[186,191,193],{"class":192},"sScJk","npm",[186,195,197],{"class":196},"sZZnC"," install",[186,199,200],{"class":196}," @nolag/iot",[186,202,203],{"class":196}," @nolag/js-sdk\n",[205,206,208],"note",{"title":207},"Shared connection",[15,209,210,211,214,215,218,219,222,223,226],{},"One core NoLag client can back several wrapper SDKs at once, for example IoT telemetry, a dashboard, and notify on a single socket, as long as each wrapper uses a distinct ",[36,212,213],{},"appName",". Each wrapper attaches its handlers on construction and releases them with ",[36,216,217],{},"detach()",", and never touches the socket itself. Your app owns ",[36,220,221],{},"connect()"," and ",[36,224,225],{},"disconnect()",".",[19,228,230],{"id":229},"quick-start","Quick Start",[173,232,233],{},[176,234,239],{"className":235,"code":236,"filename":237,"language":238,"meta":182,"style":182},"language-typescript shiki shiki-themes github-light github-dark","import { NoLag } from '@nolag/js-sdk'\nimport { NoLagIoT } from '@nolag/iot'\n\n// The app owns one core client. In a browser, pass a token provider so the\n// SDK can mint fresh short-lived client tokens from your backend.\nconst client = NoLag(async () => (await (await fetch('/api/nolag-token')).json()).token)\n\n// Inject the client into the IoT wrapper (role: 'device' or 'controller')\nconst iot = new NoLagIoT({ client, deviceId: 'device-007', role: 'controller' })\n\nawait client.connect()   // the app owns the connection\nawait iot.ready()        // wrapper setup complete\n\n// Join a device group (organised by fleet, location, or function)\nconst group = await iot.joinGroup('sensors-floor-3')\n\n// ── Device side ───────────────────────────────────────────────────────────────\n\n// Send a telemetry reading\ngroup.sendTelemetry('temperature', 22.4, {\n  unit: 'celsius',\n  sensorId: 'tmp_01',\n})\n\ngroup.sendTelemetry('humidity', 61, { unit: 'percent' })\n\n// Listen for commands sent by controllers\ngroup.on('command', async ({ command }) => {\n  console.log('Received command:', command.name, command.params)\n\n  // Execute the command...\n  const result = await handleCommand(command)\n\n  // Acknowledge success\n  await group.ackCommand(command.commandId, 'success', result)\n})\n\n// ── Controller side ───────────────────────────────────────────────────────────\n\n// Watch all telemetry from the group\ngroup.on('telemetry', ({ deviceId, sensorId, value, opts, timestamp }) => {\n  console.log(`[${deviceId}] ${sensorId}: ${value}`)\n})\n\n// Retrieve the last known reading for a specific sensor\nconst reading = await group.getTelemetry('device-007', 'temperature')\nconsole.log('Last temperature:', reading)\n\n// Send a command (returns a Promise that resolves when the device acks)\ntry {\n  const cmd = await group.sendCommand('device-007', 'reboot', {\n    delay: 5000,\n  })\n  // Promise resolves once the device calls ackCommand\n  console.log('Command acked by device:', cmd.status)\n} catch (err) {\n  // Throws if the device does not ack within the configured timeout\n  console.error('Command timed out or rejected:', err)\n}\n\n// Monitor ack events\ngroup.on('commandAck', ({ commandId, deviceId, status, result }) => {\n  console.log(`Command ${commandId} acked by ${deviceId} with status ${status}`)\n})\n\n// Presence\niot.on('deviceOnline', ({ deviceId }) => console.log('Online:', deviceId))\niot.on('deviceOffline', ({ deviceId }) => console.log('Offline:', deviceId))\n\n// Teardown: the wrapper releases its handlers; the app closes the socket.\niot.detach()\nclient.disconnect()\n","TypeScript","typescript",[36,240,241,257,270,277,284,290,345,350,356,387,392,409,426,431,437,463,468,474,479,485,508,520,531,537,542,567,572,578,610,627,632,638,657,662,668,689,694,699,705,710,716,760,789,794,799,805,832,848,853,859,867,895,906,912,918,933,945,951,967,973,978,984,1021,1049,1054,1059,1065,1099,1130,1135,1141,1152],{"__ignoreMap":182},[186,242,243,247,251,254],{"class":188,"line":189},[186,244,246],{"class":245},"szBVR","import",[186,248,250],{"class":249},"sVt8B"," { NoLag } ",[186,252,253],{"class":245},"from",[186,255,256],{"class":196}," '@nolag/js-sdk'\n",[186,258,260,262,265,267],{"class":188,"line":259},2,[186,261,246],{"class":245},[186,263,264],{"class":249}," { NoLagIoT } ",[186,266,253],{"class":245},[186,268,269],{"class":196}," '@nolag/iot'\n",[186,271,273],{"class":188,"line":272},3,[186,274,276],{"emptyLinePlaceholder":275},true,"\n",[186,278,280],{"class":188,"line":279},4,[186,281,283],{"class":282},"sJ8bj","// The app owns one core client. In a browser, pass a token provider so the\n",[186,285,287],{"class":188,"line":286},5,[186,288,289],{"class":282},"// SDK can mint fresh short-lived client tokens from your backend.\n",[186,291,293,296,300,303,306,309,312,315,318,321,324,326,328,331,333,336,339,342],{"class":188,"line":292},6,[186,294,295],{"class":245},"const",[186,297,299],{"class":298},"sj4cs"," client",[186,301,302],{"class":245}," =",[186,304,305],{"class":192}," NoLag",[186,307,308],{"class":249},"(",[186,310,311],{"class":245},"async",[186,313,314],{"class":249}," () ",[186,316,317],{"class":245},"=>",[186,319,320],{"class":249}," (",[186,322,323],{"class":245},"await",[186,325,320],{"class":249},[186,327,323],{"class":245},[186,329,330],{"class":192}," fetch",[186,332,308],{"class":249},[186,334,335],{"class":196},"'/api/nolag-token'",[186,337,338],{"class":249},")).",[186,340,341],{"class":192},"json",[186,343,344],{"class":249},"()).token)\n",[186,346,348],{"class":188,"line":347},7,[186,349,276],{"emptyLinePlaceholder":275},[186,351,353],{"class":188,"line":352},8,[186,354,355],{"class":282},"// Inject the client into the IoT wrapper (role: 'device' or 'controller')\n",[186,357,359,361,364,366,369,372,375,378,381,384],{"class":188,"line":358},9,[186,360,295],{"class":245},[186,362,363],{"class":298}," iot",[186,365,302],{"class":245},[186,367,368],{"class":245}," new",[186,370,371],{"class":192}," NoLagIoT",[186,373,374],{"class":249},"({ client, deviceId: ",[186,376,377],{"class":196},"'device-007'",[186,379,380],{"class":249},", role: ",[186,382,383],{"class":196},"'controller'",[186,385,386],{"class":249}," })\n",[186,388,390],{"class":188,"line":389},10,[186,391,276],{"emptyLinePlaceholder":275},[186,393,395,397,400,403,406],{"class":188,"line":394},11,[186,396,323],{"class":245},[186,398,399],{"class":249}," client.",[186,401,402],{"class":192},"connect",[186,404,405],{"class":249},"()   ",[186,407,408],{"class":282},"// the app owns the connection\n",[186,410,412,414,417,420,423],{"class":188,"line":411},12,[186,413,323],{"class":245},[186,415,416],{"class":249}," iot.",[186,418,419],{"class":192},"ready",[186,421,422],{"class":249},"()        ",[186,424,425],{"class":282},"// wrapper setup complete\n",[186,427,429],{"class":188,"line":428},13,[186,430,276],{"emptyLinePlaceholder":275},[186,432,434],{"class":188,"line":433},14,[186,435,436],{"class":282},"// Join a device group (organised by fleet, location, or function)\n",[186,438,440,442,445,447,450,452,455,457,460],{"class":188,"line":439},15,[186,441,295],{"class":245},[186,443,444],{"class":298}," group",[186,446,302],{"class":245},[186,448,449],{"class":245}," await",[186,451,416],{"class":249},[186,453,454],{"class":192},"joinGroup",[186,456,308],{"class":249},[186,458,459],{"class":196},"'sensors-floor-3'",[186,461,462],{"class":249},")\n",[186,464,466],{"class":188,"line":465},16,[186,467,276],{"emptyLinePlaceholder":275},[186,469,471],{"class":188,"line":470},17,[186,472,473],{"class":282},"// ── Device side ───────────────────────────────────────────────────────────────\n",[186,475,477],{"class":188,"line":476},18,[186,478,276],{"emptyLinePlaceholder":275},[186,480,482],{"class":188,"line":481},19,[186,483,484],{"class":282},"// Send a telemetry reading\n",[186,486,488,491,494,496,499,502,505],{"class":188,"line":487},20,[186,489,490],{"class":249},"group.",[186,492,493],{"class":192},"sendTelemetry",[186,495,308],{"class":249},[186,497,498],{"class":196},"'temperature'",[186,500,501],{"class":249},", ",[186,503,504],{"class":298},"22.4",[186,506,507],{"class":249},", {\n",[186,509,511,514,517],{"class":188,"line":510},21,[186,512,513],{"class":249},"  unit: ",[186,515,516],{"class":196},"'celsius'",[186,518,519],{"class":249},",\n",[186,521,523,526,529],{"class":188,"line":522},22,[186,524,525],{"class":249},"  sensorId: ",[186,527,528],{"class":196},"'tmp_01'",[186,530,519],{"class":249},[186,532,534],{"class":188,"line":533},23,[186,535,536],{"class":249},"})\n",[186,538,540],{"class":188,"line":539},24,[186,541,276],{"emptyLinePlaceholder":275},[186,543,545,547,549,551,554,556,559,562,565],{"class":188,"line":544},25,[186,546,490],{"class":249},[186,548,493],{"class":192},[186,550,308],{"class":249},[186,552,553],{"class":196},"'humidity'",[186,555,501],{"class":249},[186,557,558],{"class":298},"61",[186,560,561],{"class":249},", { unit: ",[186,563,564],{"class":196},"'percent'",[186,566,386],{"class":249},[186,568,570],{"class":188,"line":569},26,[186,571,276],{"emptyLinePlaceholder":275},[186,573,575],{"class":188,"line":574},27,[186,576,577],{"class":282},"// Listen for commands sent by controllers\n",[186,579,581,583,586,588,591,593,595,598,602,605,607],{"class":188,"line":580},28,[186,582,490],{"class":249},[186,584,585],{"class":192},"on",[186,587,308],{"class":249},[186,589,590],{"class":196},"'command'",[186,592,501],{"class":249},[186,594,311],{"class":245},[186,596,597],{"class":249}," ({ ",[186,599,601],{"class":600},"s4XuR","command",[186,603,604],{"class":249}," }) ",[186,606,317],{"class":245},[186,608,609],{"class":249}," {\n",[186,611,613,616,619,621,624],{"class":188,"line":612},29,[186,614,615],{"class":249},"  console.",[186,617,618],{"class":192},"log",[186,620,308],{"class":249},[186,622,623],{"class":196},"'Received command:'",[186,625,626],{"class":249},", command.name, command.params)\n",[186,628,630],{"class":188,"line":629},30,[186,631,276],{"emptyLinePlaceholder":275},[186,633,635],{"class":188,"line":634},31,[186,636,637],{"class":282},"  // Execute the command...\n",[186,639,641,644,647,649,651,654],{"class":188,"line":640},32,[186,642,643],{"class":245},"  const",[186,645,646],{"class":298}," result",[186,648,302],{"class":245},[186,650,449],{"class":245},[186,652,653],{"class":192}," handleCommand",[186,655,656],{"class":249},"(command)\n",[186,658,660],{"class":188,"line":659},33,[186,661,276],{"emptyLinePlaceholder":275},[186,663,665],{"class":188,"line":664},34,[186,666,667],{"class":282},"  // Acknowledge success\n",[186,669,671,674,677,680,683,686],{"class":188,"line":670},35,[186,672,673],{"class":245},"  await",[186,675,676],{"class":249}," group.",[186,678,679],{"class":192},"ackCommand",[186,681,682],{"class":249},"(command.commandId, ",[186,684,685],{"class":196},"'success'",[186,687,688],{"class":249},", result)\n",[186,690,692],{"class":188,"line":691},36,[186,693,536],{"class":249},[186,695,697],{"class":188,"line":696},37,[186,698,276],{"emptyLinePlaceholder":275},[186,700,702],{"class":188,"line":701},38,[186,703,704],{"class":282},"// ── Controller side ───────────────────────────────────────────────────────────\n",[186,706,708],{"class":188,"line":707},39,[186,709,276],{"emptyLinePlaceholder":275},[186,711,713],{"class":188,"line":712},40,[186,714,715],{"class":282},"// Watch all telemetry from the group\n",[186,717,719,721,723,725,728,731,734,736,739,741,744,746,749,751,754,756,758],{"class":188,"line":718},41,[186,720,490],{"class":249},[186,722,585],{"class":192},[186,724,308],{"class":249},[186,726,727],{"class":196},"'telemetry'",[186,729,730],{"class":249},", ({ ",[186,732,733],{"class":600},"deviceId",[186,735,501],{"class":249},[186,737,738],{"class":600},"sensorId",[186,740,501],{"class":249},[186,742,743],{"class":600},"value",[186,745,501],{"class":249},[186,747,748],{"class":600},"opts",[186,750,501],{"class":249},[186,752,753],{"class":600},"timestamp",[186,755,604],{"class":249},[186,757,317],{"class":245},[186,759,609],{"class":249},[186,761,763,765,767,769,772,774,777,779,782,784,787],{"class":188,"line":762},42,[186,764,615],{"class":249},[186,766,618],{"class":192},[186,768,308],{"class":249},[186,770,771],{"class":196},"`[${",[186,773,733],{"class":249},[186,775,776],{"class":196},"}] ${",[186,778,738],{"class":249},[186,780,781],{"class":196},"}: ${",[186,783,743],{"class":249},[186,785,786],{"class":196},"}`",[186,788,462],{"class":249},[186,790,792],{"class":188,"line":791},43,[186,793,536],{"class":249},[186,795,797],{"class":188,"line":796},44,[186,798,276],{"emptyLinePlaceholder":275},[186,800,802],{"class":188,"line":801},45,[186,803,804],{"class":282},"// Retrieve the last known reading for a specific sensor\n",[186,806,808,810,813,815,817,819,822,824,826,828,830],{"class":188,"line":807},46,[186,809,295],{"class":245},[186,811,812],{"class":298}," reading",[186,814,302],{"class":245},[186,816,449],{"class":245},[186,818,676],{"class":249},[186,820,821],{"class":192},"getTelemetry",[186,823,308],{"class":249},[186,825,377],{"class":196},[186,827,501],{"class":249},[186,829,498],{"class":196},[186,831,462],{"class":249},[186,833,835,838,840,842,845],{"class":188,"line":834},47,[186,836,837],{"class":249},"console.",[186,839,618],{"class":192},[186,841,308],{"class":249},[186,843,844],{"class":196},"'Last temperature:'",[186,846,847],{"class":249},", reading)\n",[186,849,851],{"class":188,"line":850},48,[186,852,276],{"emptyLinePlaceholder":275},[186,854,856],{"class":188,"line":855},49,[186,857,858],{"class":282},"// Send a command (returns a Promise that resolves when the device acks)\n",[186,860,862,865],{"class":188,"line":861},50,[186,863,864],{"class":245},"try",[186,866,609],{"class":249},[186,868,870,872,875,877,879,881,884,886,888,890,893],{"class":188,"line":869},51,[186,871,643],{"class":245},[186,873,874],{"class":298}," cmd",[186,876,302],{"class":245},[186,878,449],{"class":245},[186,880,676],{"class":249},[186,882,883],{"class":192},"sendCommand",[186,885,308],{"class":249},[186,887,377],{"class":196},[186,889,501],{"class":249},[186,891,892],{"class":196},"'reboot'",[186,894,507],{"class":249},[186,896,898,901,904],{"class":188,"line":897},52,[186,899,900],{"class":249},"    delay: ",[186,902,903],{"class":298},"5000",[186,905,519],{"class":249},[186,907,909],{"class":188,"line":908},53,[186,910,911],{"class":249},"  })\n",[186,913,915],{"class":188,"line":914},54,[186,916,917],{"class":282},"  // Promise resolves once the device calls ackCommand\n",[186,919,921,923,925,927,930],{"class":188,"line":920},55,[186,922,615],{"class":249},[186,924,618],{"class":192},[186,926,308],{"class":249},[186,928,929],{"class":196},"'Command acked by device:'",[186,931,932],{"class":249},", cmd.status)\n",[186,934,936,939,942],{"class":188,"line":935},56,[186,937,938],{"class":249},"} ",[186,940,941],{"class":245},"catch",[186,943,944],{"class":249}," (err) {\n",[186,946,948],{"class":188,"line":947},57,[186,949,950],{"class":282},"  // Throws if the device does not ack within the configured timeout\n",[186,952,954,956,959,961,964],{"class":188,"line":953},58,[186,955,615],{"class":249},[186,957,958],{"class":192},"error",[186,960,308],{"class":249},[186,962,963],{"class":196},"'Command timed out or rejected:'",[186,965,966],{"class":249},", err)\n",[186,968,970],{"class":188,"line":969},59,[186,971,972],{"class":249},"}\n",[186,974,976],{"class":188,"line":975},60,[186,977,276],{"emptyLinePlaceholder":275},[186,979,981],{"class":188,"line":980},61,[186,982,983],{"class":282},"// Monitor ack events\n",[186,985,987,989,991,993,996,998,1001,1003,1005,1007,1010,1012,1015,1017,1019],{"class":188,"line":986},62,[186,988,490],{"class":249},[186,990,585],{"class":192},[186,992,308],{"class":249},[186,994,995],{"class":196},"'commandAck'",[186,997,730],{"class":249},[186,999,1000],{"class":600},"commandId",[186,1002,501],{"class":249},[186,1004,733],{"class":600},[186,1006,501],{"class":249},[186,1008,1009],{"class":600},"status",[186,1011,501],{"class":249},[186,1013,1014],{"class":600},"result",[186,1016,604],{"class":249},[186,1018,317],{"class":245},[186,1020,609],{"class":249},[186,1022,1024,1026,1028,1030,1033,1035,1038,1040,1043,1045,1047],{"class":188,"line":1023},63,[186,1025,615],{"class":249},[186,1027,618],{"class":192},[186,1029,308],{"class":249},[186,1031,1032],{"class":196},"`Command ${",[186,1034,1000],{"class":249},[186,1036,1037],{"class":196},"} acked by ${",[186,1039,733],{"class":249},[186,1041,1042],{"class":196},"} with status ${",[186,1044,1009],{"class":249},[186,1046,786],{"class":196},[186,1048,462],{"class":249},[186,1050,1052],{"class":188,"line":1051},64,[186,1053,536],{"class":249},[186,1055,1057],{"class":188,"line":1056},65,[186,1058,276],{"emptyLinePlaceholder":275},[186,1060,1062],{"class":188,"line":1061},66,[186,1063,1064],{"class":282},"// Presence\n",[186,1066,1068,1071,1073,1075,1078,1080,1082,1084,1086,1089,1091,1093,1096],{"class":188,"line":1067},67,[186,1069,1070],{"class":249},"iot.",[186,1072,585],{"class":192},[186,1074,308],{"class":249},[186,1076,1077],{"class":196},"'deviceOnline'",[186,1079,730],{"class":249},[186,1081,733],{"class":600},[186,1083,604],{"class":249},[186,1085,317],{"class":245},[186,1087,1088],{"class":249}," console.",[186,1090,618],{"class":192},[186,1092,308],{"class":249},[186,1094,1095],{"class":196},"'Online:'",[186,1097,1098],{"class":249},", deviceId))\n",[186,1100,1102,1104,1106,1108,1111,1113,1115,1117,1119,1121,1123,1125,1128],{"class":188,"line":1101},68,[186,1103,1070],{"class":249},[186,1105,585],{"class":192},[186,1107,308],{"class":249},[186,1109,1110],{"class":196},"'deviceOffline'",[186,1112,730],{"class":249},[186,1114,733],{"class":600},[186,1116,604],{"class":249},[186,1118,317],{"class":245},[186,1120,1088],{"class":249},[186,1122,618],{"class":192},[186,1124,308],{"class":249},[186,1126,1127],{"class":196},"'Offline:'",[186,1129,1098],{"class":249},[186,1131,1133],{"class":188,"line":1132},69,[186,1134,276],{"emptyLinePlaceholder":275},[186,1136,1138],{"class":188,"line":1137},70,[186,1139,1140],{"class":282},"// Teardown: the wrapper releases its handlers; the app closes the socket.\n",[186,1142,1144,1146,1149],{"class":188,"line":1143},71,[186,1145,1070],{"class":249},[186,1147,1148],{"class":192},"detach",[186,1150,1151],{"class":249},"()\n",[186,1153,1155,1158,1161],{"class":188,"line":1154},72,[186,1156,1157],{"class":249},"client.",[186,1159,1160],{"class":192},"disconnect",[186,1162,1151],{"class":249},[19,1164,1166],{"id":1165},"api-reference","API Reference",[41,1168,38],{"id":1169},"nolagiot-1",[1171,1172,1174],"h4",{"id":1173},"constructor-options","Constructor Options",[112,1176,1177,1190],{},[115,1178,1179],{},[118,1180,1181,1184,1187],{},[121,1182,1183],{},"Option",[121,1185,1186],{},"Type",[121,1188,1189],{},"Description",[131,1191,1192,1210,1224,1238,1257,1272,1288,1303,1321,1338],{},[118,1193,1194,1199,1204],{},[136,1195,1196],{},[36,1197,1198],{},"client",[136,1200,1201],{},[36,1202,1203],{},"NoLagSocket",[136,1205,1206,1209],{},[27,1207,1208],{},"Required."," The injected core NoLag client the app owns and connects.",[118,1211,1212,1216,1221],{},[136,1213,1214],{},[36,1215,733],{},[136,1217,1218],{},[36,1219,1220],{},"string",[136,1222,1223],{},"Stable device identifier (auto-generated if omitted).",[118,1225,1226,1231,1235],{},[136,1227,1228],{},[36,1229,1230],{},"deviceName",[136,1232,1233],{},[36,1234,1220],{},[136,1236,1237],{},"Optional human-readable device name.",[118,1239,1240,1245,1250],{},[136,1241,1242],{},[36,1243,1244],{},"role",[136,1246,1247],{},[36,1248,1249],{},"'device' | 'controller'",[136,1251,1252,1253,1256],{},"Whether this client acts as a device or a controller (default ",[36,1254,1255],{},"'device'",").",[118,1258,1259,1264,1269],{},[136,1260,1261],{},[36,1262,1263],{},"metadata",[136,1265,1266],{},[36,1267,1268],{},"Record\u003Cstring, unknown>",[136,1270,1271],{},"Optional custom data attached to device presence.",[118,1273,1274,1278,1282],{},[136,1275,1276],{},[36,1277,213],{},[136,1279,1280],{},[36,1281,1220],{},[136,1283,1284,1285,1256],{},"NoLag app for topic prefixes (default ",[36,1286,1287],{},"'iot'",[118,1289,1290,1295,1300],{},[136,1291,1292],{},[36,1293,1294],{},"groups",[136,1296,1297],{},[36,1298,1299],{},"string[]",[136,1301,1302],{},"Groups to join once the wrapper is ready.",[118,1304,1305,1310,1315],{},[136,1306,1307],{},[36,1308,1309],{},"maxTelemetryPoints",[136,1311,1312],{},[36,1313,1314],{},"number",[136,1316,1317,1318,1256],{},"Max telemetry readings retained per device/sensor key (default ",[36,1319,1320],{},"1000",[118,1322,1323,1328,1332],{},[136,1324,1325],{},[36,1326,1327],{},"commandTimeout",[136,1329,1330],{},[36,1331,1314],{},[136,1333,1334,1335,1256],{},"Command acknowledgment timeout in ms (default ",[36,1336,1337],{},"30000",[118,1339,1340,1345,1350],{},[136,1341,1342],{},[36,1343,1344],{},"debug",[136,1346,1347],{},[36,1348,1349],{},"boolean",[136,1351,1352,1353,1256],{},"Enable wrapper debug logging (default ",[36,1354,1355],{},"false",[112,1357,1358,1370],{},[115,1359,1360],{},[118,1361,1362,1365,1368],{},[121,1363,1364],{},"Method",[121,1366,1367],{},"Returns",[121,1369,1189],{},[131,1371,1372,1387,1401,1415,1429],{},[118,1373,1374,1379,1384],{},[136,1375,1376],{},[36,1377,1378],{},"ready()",[136,1380,1381],{},[36,1382,1383],{},"Promise\u003Cvoid>",[136,1385,1386],{},"Resolves once wrapper setup completed.",[118,1388,1389,1393,1398],{},[136,1390,1391],{},[36,1392,217],{},[136,1394,1395],{},[36,1396,1397],{},"void",[136,1399,1400],{},"Release this wrapper's handlers and topics; terminal, never closes the socket.",[118,1402,1403,1407,1412],{},[136,1404,1405],{},[36,1406,85],{},[136,1408,1409],{},[36,1410,1411],{},"Promise\u003CDeviceGroup>",[136,1413,1414],{},"Subscribe to a device group. Returns the group instance.",[118,1416,1417,1422,1426],{},[136,1418,1419],{},[36,1420,1421],{},"leaveGroup(name)",[136,1423,1424],{},[36,1425,1383],{},[136,1427,1428],{},"Unsubscribe from a device group and release its resources.",[118,1430,1431,1436,1441],{},[136,1432,1433],{},[36,1434,1435],{},"getOnlineDevices()",[136,1437,1438],{},[36,1439,1440],{},"Device[]",[136,1442,1443],{},"Return all devices currently present in the lobby.",[41,1445,1447],{"id":1446},"nolagiot-events","NoLagIoT Events",[112,1449,1450,1462],{},[115,1451,1452],{},[118,1453,1454,1457,1460],{},[121,1455,1456],{},"Event",[121,1458,1459],{},"Payload",[121,1461,1189],{},[131,1463,1464,1477,1492,1504,1518,1533],{},[118,1465,1466,1471,1474],{},[136,1467,1468],{},[36,1469,1470],{},"connected",[136,1472,1473],{},"none",[136,1475,1476],{},"WebSocket connection established.",[118,1478,1479,1484,1489],{},[136,1480,1481],{},[36,1482,1483],{},"disconnected",[136,1485,1486],{},[36,1487,1488],{},"reason: string",[136,1490,1491],{},"Connection closed.",[118,1493,1494,1499,1501],{},[136,1495,1496],{},[36,1497,1498],{},"reconnected",[136,1500,1473],{},[136,1502,1503],{},"Connection restored; room membership and presence are restored automatically.",[118,1505,1506,1510,1515],{},[136,1507,1508],{},[36,1509,958],{},[136,1511,1512],{},[36,1513,1514],{},"error: Error",[136,1516,1517],{},"A transport or protocol error occurred.",[118,1519,1520,1525,1530],{},[136,1521,1522],{},[36,1523,1524],{},"deviceOnline",[136,1526,1527],{},[36,1528,1529],{},"device: Device",[136,1531,1532],{},"A device joined the lobby.",[118,1534,1535,1540,1544],{},[136,1536,1537],{},[36,1538,1539],{},"deviceOffline",[136,1541,1542],{},[36,1543,1529],{},[136,1545,1546],{},"A device left the lobby.",[41,1548,89],{"id":1549},"devicegroup",[112,1551,1552,1565],{},[115,1553,1554],{},[118,1555,1556,1558,1561,1563],{},[121,1557,1364],{},[121,1559,1560],{},"Role",[121,1562,1367],{},[121,1564,1189],{},[131,1566,1567,1587,1605,1623],{},[118,1568,1569,1574,1577,1581],{},[136,1570,1571],{},[36,1572,1573],{},"sendTelemetry(sensorId, value, opts?)",[136,1575,1576],{},"Device",[136,1578,1579],{},[36,1580,1397],{},[136,1582,1583,1584,1586],{},"Publish a sensor reading to the group. ",[36,1585,748],{}," carries metadata such as unit or tags.",[118,1588,1589,1594,1597,1602],{},[136,1590,1591],{},[36,1592,1593],{},"getTelemetry(deviceId?, sensorId?)",[136,1595,1596],{},"Both",[136,1598,1599],{},[36,1600,1601],{},"Promise\u003CTelemetryReading[]>",[136,1603,1604],{},"Fetch the most recent telemetry. Omit arguments to get all devices and sensors.",[118,1606,1607,1612,1615,1620],{},[136,1608,1609],{},[36,1610,1611],{},"sendCommand(targetDeviceId, command, params?)",[136,1613,1614],{},"Controller",[136,1616,1617],{},[36,1618,1619],{},"Promise\u003CDeviceCommand>",[136,1621,1622],{},"Dispatch a named command to a device. Resolves when the device acknowledges, or rejects on timeout.",[118,1624,1625,1630,1632,1636],{},[136,1626,1627],{},[36,1628,1629],{},"ackCommand(commandId, status, result?)",[136,1631,1576],{},[136,1633,1634],{},[36,1635,1397],{},[136,1637,1638,1639,1641,1642,1644,1645,226],{},"Send an acknowledgment for a received command. ",[36,1640,1009],{}," is ",[36,1643,685],{}," or ",[36,1646,1647],{},"'error'",[41,1649,1651],{"id":1650},"devicegroup-events","DeviceGroup Events",[112,1653,1654,1664],{},[115,1655,1656],{},[118,1657,1658,1660,1662],{},[121,1659,1456],{},[121,1661,1459],{},[121,1663,1189],{},[131,1665,1666,1680,1694,1709,1723],{},[118,1667,1668,1672,1677],{},[136,1669,1670],{},[36,1671,93],{},[136,1673,1674],{},[36,1675,1676],{},"{ deviceId, sensorId, value, opts?, timestamp }",[136,1678,1679],{},"A telemetry reading was received from a device in the group.",[118,1681,1682,1686,1691],{},[136,1683,1684],{},[36,1685,601],{},[136,1687,1688],{},[36,1689,1690],{},"{ command: DeviceCommand }",[136,1692,1693],{},"A command was dispatched to this device (device role only).",[118,1695,1696,1701,1706],{},[136,1697,1698],{},[36,1699,1700],{},"commandAck",[136,1702,1703],{},[36,1704,1705],{},"{ commandId, deviceId, status, result? }",[136,1707,1708],{},"A device acknowledged a previously dispatched command.",[118,1710,1711,1716,1720],{},[136,1712,1713],{},[36,1714,1715],{},"deviceJoined",[136,1717,1718],{},[36,1719,1529],{},[136,1721,1722],{},"A device joined this group.",[118,1724,1725,1730,1734],{},[136,1726,1727],{},[36,1728,1729],{},"deviceLeft",[136,1731,1732],{},[36,1733,1529],{},[136,1735,1736],{},"A device left this group.",[1738,1739,1740],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":182,"searchDepth":259,"depth":259,"links":1742},[1743,1746,1747,1748,1749],{"id":21,"depth":259,"text":22,"children":1744},[1745],{"id":43,"depth":272,"text":44},{"id":72,"depth":259,"text":73},{"id":170,"depth":259,"text":171},{"id":229,"depth":259,"text":230},{"id":1165,"depth":259,"text":1166,"children":1750},[1751,1752,1753,1754],{"id":1169,"depth":272,"text":38},{"id":1446,"depth":272,"text":1447},{"id":1549,"depth":272,"text":89},{"id":1650,"depth":272,"text":1651},"IoT device telemetry and command dispatch with acknowledgment tracking for connected device fleets.","md",{},"/docs/high-level-sdks/iot",{"title":5,"description":1755},"docs/high-level-sdks/iot","Ztd3n1SXk1m6nZ8jRlOttyHGeLCxBx9Bkr3FKRKvxFg",1788160343868]