36 What’s changed since v3?
UnetStack v7 keeps the same architecture as UnetStack v3 — a stack of agents that implement services, accessed from the shell, Groovy scripts or the UnetSocket API — so most code, scripts and applications written for UnetStack v3 continue to work with little or no change. A number of things have changed, however: the composition of the default stack, the set of services, some message and parameter contracts, the shell commands for a few features, and the tooling that ships with the stack.
This appendix is not an exhaustive changelog. It summarizes the changes you are most likely to notice (or trip over) when coming from UnetStack v3, with migration guidance attached to each. Where the right action depends on something we could not confirm from the sources, it is flagged in a CHECK callout for you to verify against your own deployment.
36.1 Framework & versions
- UnetStack is now at v7 (the handbook you are reading documents v7.0.1), up from the v3.x series. Most user-facing concepts (services, agents, messages, parameters, the shell, UnetSocket) are unchanged, so the migration effort is concentrated in the specific areas called out below rather than in a wholesale rewrite.
- fjåge has been updated. UnetStack v7 ships with fjåge 2.5.0 and Groovy 2.5.23. If you depend on fjåge directly (for example, custom gateways or agents built against the fjåge API), rebuild against the bundled version and check for any fjåge API changes.
Confirm the exact fjåge version your UnetStack v3 deployment used (and the minimum fjåge/ Java versions your own code targets) so you can assess the size of the fjåge upgrade. Also confirm whether any of your custom agents rely on Groovy language features that differ between the Groovy version bundled with UnetStack v3 and Groovy 2.5.23.
36.2 The default stack
The most visible change is in the agents that are loaded by default (etc/setup.groovy). The table below summarizes the default stack in each version:
| Role | UnetStack v3 (default) | UnetStack v7 (default) |
|---|---|---|
Link (uwlink) |
ReliableLink |
ECLink (erasure-coded) |
| Transport | SWTransport (as transport) |
Caddy / CaddyLite (as caddy) |
| Remote access | RemoteControl (as remote) |
folded into the caddy agent |
State persistence (statemanager) |
StateManager |
removed (see below) |
- The default underwater link is now
ECLink(uwlink). Where UnetStack v3 loadedorg.arl.unet.link.ReliableLinkasuwlink, UnetStack v7 loadsorg.arl.unet.link.ECLink.ECLinkuses erasure coding to deliver datagrams faster and more robustly over the same channels, avoiding the per-fragment acknowledgement round-trips thatReliableLinkrelies on (Chapter 18). Theuwlinkname and theLINK+DATAGRAMservice contract are unchanged, so code that sendsDatagramReqs touwlinkkeeps working.Migration: no change needed for normal use. If you set
ReliableLink-specific parameters (e.g.acks,reservationGuardTime), note thatECLinkexposes a different parameter set (reliableExtra,unreliableExtra,fragmentLength,controlChannel/dataChannel, …, see Chapter 18).ReliableLinkis deprecated but still available, so a deployment that genuinely needs it can load it explicitly:// bring back the old link, if you really need it container.add 'uwlink', new org.arl.unet.link.ReliableLink()
- Transport and remote access are now one agent. UnetStack v3 used
org.arl.unet.transport.SWTransport(loaded astransport) for theTRANSPORTservice and a separateorg.arl.unet.remote.RemoteControlagent (loaded asremote) for theREMOTEservice. UnetStack v7 loads a single agent namedcaddythat provides theTRANSPORT,REMOTEandDATAGRAMservices. The base implementationorg.arl.unet.transport.CaddyLiteis part of the standard distribution; the licensedorg.arl.unet.transport.Caddyis a drop-in replacement that adds QoS (priority, TTL, fairness, rule-based routing) and resumable file transfers (Chapter 24). The shell still providestransportandremotehandles that resolve to the agent through its services, so interactive usage reads the same as before.Migration: shell usage is unchanged —
ping,tell,rsh,fput/fgetwork as before, and remote shell/file operations are still gated byremote.enable = trueon the node being accessed (Chapter 24). Code that looks agents up by service (agentForService(Services.TRANSPORT),agentForService(Services.REMOTE)) is unaffected. Code that hard-codes the classorg.arl.unet.remote.RemoteControlor the agent nametransportshould look the agent up by service instead.SWTransportis deprecated but still available (Chapter 23) if you need the old stop-and-wait behavior.// robust: works in both versions def remote = agentForService Services.REMOTERemote acknowledgements work differently. The v3
ack on/ack offshell command, theackfield ofRemoteTextReqand friends, and the?-prefix trick for getting remote command output are all gone. In UnetStack v7,rshsends the command output back by default (append a trailing;to suppress it),telltakes an optional reliability argument (e.g.tell 31, 'hello', true), and theprogresscommand reports on ongoing file transfers (Chapter 24). Scripts that useackor?-prefixed remote commands must be updated.
36.3 Services
The set of services in org.arl.unet.Services has changed. In UnetStack v7 the enum is:
NODE_INFO, ADDRESS_RESOLUTION, DATAGRAM, PHYSICAL, RANGING, BASEBAND, LINK, LINK_TUNING, MAC, ROUTING, ROUTE_MAINTENANCE, TRANSPORT, REMOTE, SCHEDULER, DEVICE_INFO, DOA.
New services in UnetStack v7. Three services have no UnetStack v3 counterpart:
LINK_TUNING— tuning of link parameters (Chapter 20).DEVICE_INFO— device/hardware information such as storage and status (Chapter 28).DOA— direction-of-arrival estimation (Chapter 26).- Migration: these are additive. Existing code is unaffected; new code can take advantage of them by looking up the relevant service (e.g.
agentForService(Services.DEVICE_INFO)).
All other UnetStack v3 services (
DATAGRAM,PHYSICAL,BASEBAND,RANGING,NODE_INFO,ADDRESS_RESOLUTION,LINK,MAC,ROUTING,ROUTE_MAINTENANCE,TRANSPORT,REMOTE,SCHEDULER, and the fjågeSHELLservice) carry over unchanged, with the sole exception ofSTATE_MANAGER:The State Persistence service has been removed. UnetStack v3 had a dedicated state-persistence mechanism: a
statemanageragent (org.arl.unet.state.StateManager) and asavestateshell command that wrote asaved-state.groovyfile into thescriptsfolder, which was then re-loaded automatically on reboot. UnetStack v7 has noSTATE_MANAGERservice in theServicesenum, does not load a state-manager agent in the default stack, and no longer ships theStateManagerclass or thesavestatecommand. Instead, persistence is handled by the framework: agents that need to survive a restart persist their own state through fjåge’sStoreAPI (org.arl.fjage.persistence.Store). For example, theScheduleragent (Chapter 29) saves and restores its state withgetStore()/store.put(...)/store.getById(...)rather than relying on a central state manager.- Migration:
If your workflow relied on
savestateto snapshot a configured node, replace it. The recommended approach is to capture your node configuration in anetc/setup.groovy(or a startup.groovyscript inscripts/) that sets the parameters you need at boot — this is explicit, reviewable and version-controllable.If you wrote a custom agent that persisted state via the old
StateManager, port it to persist its own state through the fjågeStoreAPI. A sketch:import org.arl.fjage.persistence.Store // saving Store store = getStore() store.put(myState) // restoring (e.g. in startup()) Store store = getStore() def myState = store.getById(MyState, 'state')
- Migration:
The Scheduler service has been redesigned. The UnetStack v3 sleep-schedule API —
AddScheduledSleepReq,RemoveScheduledSleepReq,GetSleepScheduleReq,SleepScheduleRsp, thertcparameter, and theaddsleep/showsleep/rmsleepshell commands — is gone. UnetStack v7 schedules sleep/wake (and arbitrary tasks) throughSleepReq,StayAwakeReqandAddScheduledTaskReq, withsleep,cronadd,crontabandcronrmshell commands (Chapter 29).- Migration: v3 sleep-schedule scripts break silently (the commands no longer exist); rewrite them against the new commands/messages. Epoch-time-based one-shot sleeps map naturally onto
sleep; recurring schedules ontocronadd.
- Migration: v3 sleep-schedule scripts break silently (the commands no longer exist); rewrite them against the new commands/messages. Epoch-time-based one-shot sleeps map naturally onto
36.4 Messages & parameters
A few message and parameter contracts changed between v3 and v7. These are the most common causes of silently-broken v3 code:
- Datagram notifications are delivered on a global topic. In UnetStack v3, each
DATAGRAMprovider publishedDatagramNtfs on its own agent topic (so you wouldsubscribe phyorsubscribe uwlinkto receive data), and frames overheard from other nodes were published on a separateSNOOPsub-topic (topic(phy, Physical.SNOOP)). In UnetStack v7, this is inverted: datagrams addressed to your node (or broadcast) appear on the globalTopics.DATAGRAMtopic, while the provider’s own agent topic carries frames overheard from other nodes (Chapter 16, Chapter 17). ThePhysical.SNOOPconstant no longer exists.- Migration: code that subscribes to a provider’s topic to receive its own data must subscribe to
topic(org.arl.unet.Topics.DATAGRAM)instead; code that used theSNOOPsub-topic should subscribe to the provider’s agent topic.
- Migration: code that subscribes to a provider’s topic to receive its own data must subscribe to
DatagramCancelReqis nowCancelReq. Same role (cancel a pending datagram by message ID), new name.- Raw frames and collision notifications are gone.
TxRawFrameReqandCollisionNtfno longer exist in thePHYSICALservice. - Several
phyparameters moved or were removed.propagationSpeed,refPowerLevel,rxSensitivity,errorDetection,llrandjanusare no longerphy/phy[]parameters; the power-reference and signal-level parameters now live on the baseband agent (bb.*, see Chapter 27). - JANUS moved to the
AUXchannel. In UnetStack v3, JANUS was transmitted as frame type 3 (enabled via thejanuschannel parameter); in UnetStack v7 it is carried on theAUXchannel alongside other standardized schemes (Section 17.9). - Node orientation conventions changed. The v3
nodeinfoparametersheading(0° = North, measured clockwise) andturnRateare replaced byyaw(0° = East, measured anticlockwise) andyawRate(Chapter 14). Simulation scripts using the v3 motion-model properties must be updated to the new names and the new angle convention.
36.5 Shell, scripting & APIs
- The shell is unchanged in spirit. It still accepts Groovy, agents are still reachable by name (e.g.
router,caddy) or shell handles (transport,remote), and providers can still be located by service withagentForService(Services.<NAME>). Most UnetStack v3 shell scripts run unchanged. Watch for the specific command/agent changes above: anything tied to the oldremoteagent class, the old link/transport classes,savestate,addsleep, orack. - Java packages are unchanged. Services and most agents keep their UnetStack v3 package names under
org.arl.unet.*(e.g.org.arl.unet.Services,org.arl.unet.nodeinfo.NodeInfo,org.arl.unet.addr.AddressResolution,org.arl.unet.net.Router). The changes are at the level of which agent class is loaded by default (e.g.ECLinkvsReliableLink,Caddy/CaddyLitevsSWTransport), not a blanket package rename. FSMBuildermoved to fjåge. UnetStack v3 providedorg.arl.unet.FSMBuilder, which custom agents typically picked up throughimport org.arl.unet.*. That class has been removed in favor of the identicalorg.arl.fjage.groovy.FSMBuilder— add an explicitimport org.arl.fjage.groovy.FSMBuilderto any agent that builds FSMs with it (theorg.arl.fjage.*star import does not cover the subpackage). As a bonus, FSM definitions can now be statically compiled (see Chapter 33); avoid building FSMs inside non-static inner classes — use astaticnested class with an explicit reference to the agent.- The UnetSocket API is preserved. UnetSocket remains available across Java, Groovy, Python (and the other supported language bindings), with the same connect/send/receive model. Applications written against UnetSocket for UnetStack v3 should port with little or no change.
- Migration: rebuild against the UnetStack v7 libraries and re-run your tests. Prefer locating agents by service rather than by class name so that the default-stack agent swaps above do not affect you.
Confirm there are no breaking changes in the UnetSocket client libraries / fjåge gateway protocol between the version your applications were built against and UnetStack v7 (2.5-era fjåge). In particular, verify the Python unetpy/fjagepy versions you use are compatible, and re-test any C or Julia bindings. If you maintain custom agents, also verify that the UnetAgent lifecycle hooks and parameter-declaration conventions you use match those documented in Part III and the developer chapters in Part IV.
36.6 Tooling & editions
- The web IDE is gone. UnetStack v3 shipped a simulator IDE (
bin/unet sim) with a file browser, script editor, simulation shell and a map view of the simulated network. UnetStack v7 drops it: simulations are run from the command line (bin/unet <script.groovy>, see Chapter 34), and each simulated node exposes its own web shell for interactive use. Files on a node (scripts, agent classes) can still be created and edited through the node’s web interface. - Unet audio is not included in the community release. The soundcard-based acoustic modem (Unet audio) that UnetStack v3 bundled in its community download is available only in the commercial editions of UnetStack v7. The community release still includes the full simulator, which is what this handbook’s examples run on.
36.7 Quick checklist
When moving a UnetStack v3 deployment or project to UnetStack v7:
- Rebuild against the UnetStack v7 / fjåge 2.5 libraries.
- Stop referencing deprecated/removed classes directly — look up agents by service (
agentForService(...)) instead of by class. Affected: the link (ReliableLink→ECLink), transport (SWTransport→Caddy/CaddyLiteascaddy) and remote (RemoteControl→ folded intocaddy). - Update datagram subscriptions:
subscribe phy/subscribe uwlink→subscribe topic(Topics.DATAGRAM);topic(phy, Physical.SNOOP)→ the provider’s agent topic. - Rename
DatagramCancelReq→CancelReq; remove any use ofTxRawFrameReq/CollisionNtf; movephypower/sensitivity parameter accesses tobb.*. - Add
import org.arl.fjage.groovy.FSMBuilderto any custom agent that builds FSMs withFSMBuilder(previouslyorg.arl.unet.FSMBuilder, reachable viaimport org.arl.unet.*). - Replace any
savestate/StateManagerusage with an explicitsetup.groovy/startup script for configuration, and with the fjågeStoreAPI for custom-agent state. - Rewrite sleep schedules:
addsleep/showsleep/rmsleep→sleep/cronadd/crontab/cronrm. - Drop
ack on/ack offand?-prefixed remote commands —rshreturns output by default (trailing;suppresses it). - Update motion-model properties:
heading/turnRate→yaw/yawRate, converting to the new angle convention (0° = East, anticlockwise). - Review parameters you set on
uwlinkand the transport agent, since the default agents expose different parameter sets from their v3 predecessors. - Re-test your applications and shell scripts end-to-end, and address the CHECK items above for your specific deployment.