PageSourceSearch

https://meshtastic-bice.vercel.app/assets/js/6fe87a19.88392870.js

js meshtastic-bice.vercel.app collected 2026-10-03 07:20:57 UTC 17,336 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkmeshtastic=self.webpackChunkmeshtastic||[]).push([["23667"],{27614(e,n,i){i.r(n),i.d(n,{metadata:()=>t,default:()=>m,frontMatter:()=>a,contentTitle:()=>l,toc:()=>c,assets:()=>d});var t=JSON.parse('{"id":"software/meshtasticator/interactive-sim","title":"Interactive Simulator Usage Guide","description":"A usage guide for simulating multiple Meshtastic instances with TCP-based communication and configurable pathloss models.","source":"@site/versioned_docs/version-2.7/software/meshtasticator/interactive-sim.mdx","sourceDirName":"software/meshtasticator","slug":"/software/meshtasticator/interactive-sim","permalink":"/docs/2.7/software/meshtasticator/interactive-sim","draft":false,"unlisted":false,"tags":[],"version":"2.7","lastUpdatedBy":"rcarteraz","sidebarPosition":2,"frontMatter":{"id":"interactive-sim","title":"Interactive Simulator Usage Guide","sidebar_label":"Interactive Event Simulator","sidebar_position":2,"description":"A usage guide for simulating multiple Meshtastic instances with TCP-based communication and configurable pathloss models."},"sidebar":"Sidebar","previous":{"title":"Discrete Event Simulator","permalink":"/docs/2.7/software/meshtasticator/discrete-event-sim"},"next":{"title":"MeshtasticD","permalink":"/docs/2.7/meshtasticd/"}}'),s=i(91987),r=i(67008),o=i(87622);let a={id:"interactive-sim",title:"Interactive Simulator Usage Guide",sidebar_label:"Interactive Event Simulator",sidebar_position:2,description:"A usage guide for simulating multiple Meshtastic instances with TCP-based communication and configurable pathloss models."},l,d={},c=[{value:"Usage",id:"usage",level:2},{value:"Using PlatformIO",id:"using-platformio",level:3},{value:"Using Docker",id:"using-docker",level:3},{value:"Running the Simulator",id:"running-the-simulator",level:2},{value:"Commands During Simulation",id:"commands-during-simulation",level:2},{value:"List of Commands",id:"list-of-commands",level:2},{value:"Usage with Script",id:"usage-with-script",level:2},{value:"Tips and Tricks",id:"tips-and-tricks",level:2},{value:"Pathloss Model",id:"pathloss-model",level:2}];function h(e){let n={a:"a",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(n.p,{children:["The Python script ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"interactiveSim.py"})})," uses ",(0,s.jsx)(n.a,{href:"/docs/2.7/meshtasticd/installation/",children:"MeshtasticD"})," to simulate multiple instances of the device software. These instances communicate using ",(0,s.jsx)(o.A,{term:"TCP",definition:"One of the three ways a client reaches a node, alongside serial and Bluetooth. Clients connect over TCP on port 4403.",routePath:"/docs/terms/",children:"TCP"})," via the script, simulating the ",(0,s.jsx)(o.A,{term:"LoRa",definition:"A low-power, long-range wireless communication technology used by Meshtastic devices to enable communication over distances of several kilometers without the need for cellular, Wi-Fi, or other traditional network infrastructures.",routePath:"/docs/terms/",children:"LoRa"})," chip. The simulator forwards messages from the sender to all nodes within range, based on their simulated positions and the selected pathloss model (see ",(0,s.jsx)(n.a,{href:"#pathloss-model",children:"Pathloss Model"}),"). ",(0,s.jsx)(n.strong,{children:"Note:"})," Packet collisions are not yet simulated."]}),"\n",(0,s.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Clone or download the repository and navigate to the Meshtasticator folder."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"(Optional) Create a virtual environment."}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Install dependencies:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"pip install -r requirements.txt\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["The simulator runs the MeshtasticD application of Meshtastic firmware. You can use either ",(0,s.jsx)(n.a,{href:"https://meshtastic.org/docs/2.7/development/firmware/build",children:"PlatformIO"})," or ",(0,s.jsx)(n.a,{href:"https://meshtastic.org/docs/2.7/software/linux/usage/#usage-with-docker",children:"Docker"})," to run the firmware:"]}),"\n",(0,s.jsx)(n.h3,{id:"using-platformio",children:"Using PlatformIO"}),"\n",(0,s.jsxs)(n.p,{children:["Select 'native' and click 'build.' Locate the generated binary file, likely in ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"firmware/.pio/build/native/"})}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Copy the ",(0,s.jsx)(n.code,{children:"program"})," file to the directory where you'll run the Python script, or provide the path as an argument with ",(0,s.jsx)(n.code,{children:"-p"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"python3 interactiveSim.py 3 -p /home/User/Meshtastic-device/.pio/build/native/program\n"})}),"\n",(0,s.jsx)(n.h3,{id:"using-docker",children:"Using Docker"}),"\n",(0,s.jsx)(n.p,{children:"The simulator pulls a Docker image that builds the latest Meshtastic firmware."}),"\n",(0,s.jsx)(n.p,{children:"Ensure the Docker SDK for Python is installed:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"pip3 install docker\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Make sure the Docker daemon or Desktop app is running. Use the ",(0,s.jsx)(n.code,{children:"-d"})," argument to launch the simulator:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"python3 interactiveSim.py 3 -d\n"})}),"\n",(0,s.jsx)(n.h2,{id:"running-the-simulator",children:"Running the Simulator"}),"\n",(0,s.jsx)(n.p,{children:"To run the interactive simulator:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"python3 interactiveSim.py [nrNodes] [-p <full-path-to-program>]\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"nrNodes"})})," (optional): Number of instances to launch. Each instance opens a terminal and a ",(0,s.jsx)(o.A,{term:"TCP",definition:"One of the three ways a client reaches a node, alongside serial and Bluetooth. Clients connect over TCP on port 4403.",routePath:"/docs/terms/",children:"TCP"})," port (starting at 4403)."]}),"\n",(0,s.jsx)(n.li,{children:"If you provide the number of nodes, they will be randomly placed; otherwise, you can manually place nodes on a plot."}),"\n",(0,s.jsxs)(n.li,{children:["After placing nodes, you can configure their ",(0,s.jsx)(n.a,{href:"https://meshtastic.org/docs/2.7/settings/config/device#role",children:"role"}),", ",(0,s.jsx)(n.code,{children:"hopLimit"}),", height (elevation), and antenna gain. Configurations are saved automatically."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Config Note",src:i(68654).A+"",width:"630",height:"433"})}),"\n",(0,s.jsx)(n.h2,{id:"commands-during-simulation",children:"Commands During Simulation"}),"\n",(0,s.jsxs)(n.p,{children:["Once the simulation starts, you can issue commands (or use a predefined ",(0,s.jsx)(n.a,{href:"#usage-with-script",children:"script"}),") to send messages between nodes. Use ",(0,s.jsx)(n.code,{children:"plot"})," to visualize message routes and airtime statistics:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Enter a message ID to see its route."}),"\n",(0,s.jsx)(n.li,{children:"Hover over arcs for information and click to remove the overlay."}),"\n",(0,s.jsx)(n.li,{children:"Two graphs display channel utilization (one-minute window) and airtime usage (hourly window) for each node."}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"Route Plot 2",src:i(5486).A+"",width:"682",height:"463"})}),"\n",(0,s.jsx)(n.h2,{id:"list-of-commands",children:"List of Commands"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"broadcast <fromNode> <txt>"})}),": Send a broadcast from node ",(0,s.jsx)(n.em,{children:"fromNode"})," with text ",(0,s.jsx)(n.em,{children:"txt"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"DM <fromNode> <toNode> <txt>"})}),": Send a Direct Message from node ",(0,s.jsx)(n.em,{children:"fromNode"}
1)," to node ",(0,s.jsx)(n.em,{children:"toNode"})," with text ",(0,s.jsx)(n.em,{children:"txt"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"traceroute <fromNode> <toNode>"})}),": Send a traceroute request from node ",(0,s.jsx)(n.em,{children:"fromNode"})," to node ",(0,s.jsx)(n.em,{children:"toNode"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"reqPos <fromNode> <toNode>"})}),": Send a position request from node ",(0,s.jsx)(n.em,{children:"fromNode"})," to node ",(0,s.jsx)(n.em,{children:"toNode"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"ping <fromNode> <toNode>"})}),": Send ping from node ",(0,s.jsx)(n.em,{children:"fromNode"})," to node ",(0,s.jsx)(n.em,{children:"toNode"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"remove <id>"})}),": Remove node ",(0,s.jsx)(n.em,{children:"id"})," from the current simulation."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"nodes <id0> [id1, etc.]"})}),": Show the node list as seen by node(s) ",(0,s.jsx)(n.em,{children:"id0"}),", ",(0,s.jsx)(n.em,{children:"id1"}),", etc."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"plot"})}),": Plot the routes of messages sent and airtime statistics."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"exit"})}),": Exit the simulator without plotting routes."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"usage-with-script",children:"Usage with Script"}),"\n",(0,s.jsxs)(n.p,{children:["Modify the ",(0,s.jsx)(n.code,{children:"try"})," clause in ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"interactiveSim.py"})})," to predefine messages. Run the simulator with the ",(0,s.jsx)(n.code,{children:"-s"})," argument:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"python3 interactiveSim.py 3 -s\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"After nodes exchange NodeInfo, they will begin sending messages."}),"\n",(0,s.jsxs)(n.li,{children:["Close the simulation manually with ",(0,s.jsx)(n.code,{children:"Ctrl+C"})," or wait for the timeout."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"tips-and-tricks",children:"Tips and Tricks"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Speeding Up NodeInfo Exchange:"}),(0,s.jsx)(n.br,{}),"\n","Disable certain modules by removing ",(0,s.jsx)(n.code,{children:"new NodeInfoModule()"})," from ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"src/modules/Modules.cpp"})})," in the firmware."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Saving and Reloading Configurations:"}),(0,s.jsx)(n.br,{}),"\n","After a simulation, node configurations are saved. You can rerun the same scenario with:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"python3 interactiveSim.py --from-file\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Modify the ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"out/nodeConfig.yaml"})})," file to adjust configurations before reloading."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsxs)(n.strong,{children:["Using the Python ",(0,s.jsx)(o.A,{term:"CLI",definition:"A text-based interface used for interacting with software or devices like Meshtastic.",routePath:"/docs/terms/",children:"CLI"}),":"]}),(0,s.jsx)(n.br,{}),"\n","You can call functions from the Node class via ",(0,s.jsx)(n.code,{children:"sim.getNodeById(<id>)"})," in ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"interactiveSim.py"})}),". Example:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:"node.setURL('<YOUR_URL>')\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"pathloss-model",children:"Pathloss Model"}),"\n",(0,s.jsx)(n.p,{children:"The simulator estimates signal propagation using a pathloss model. This is an approximation of the physical environment, so it may not be 100% accurate. The available models are:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"0"}),": Log-distance model"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"1"}),": Okumura-Hata model (small/medium cities)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"2"}),": Okumura-Hata model (metropolitan areas)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"3"}),": Okumura-Hata model (suburban environments)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"4"}),": Okumura-Hata model (rural areas)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"5"}),": 3GPP model (suburban macro-cell)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"6"}),": 3GPP model (metropolitan macro-cell)"]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["You can modify the pathloss model and area configuration in ",(0,s.jsx)(n.em,{children:(0,s.jsx)(n.code,{children:"lib/config.py"})}),". ",(0,s.jsx)(o.A,{term:"LoRa",definition:"A low-power, long-range wireless communication technology used by Meshtastic devices to enable communication over distances of several kilometers without the need for cellular, Wi-Fi, or other traditional network infrastru
1ctures.",routePath:"/docs/terms/",children:"LoRa"})," settings remain at their Meshtastic defaults unless customized during node placement."]})]})}function m(e={}){let{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},68654(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/configNode-0c406aac1a623240c52340d3eb155e39.webp"},5486(e,n,i){i.d(n,{A:()=>t});let t=i.p+"assets/images/route_plot-2-90270aa8339459f1f786284188bda1e8.webp"},67008(e,n,i){i.d(n,{R:()=>o,x:()=>a});var t=i(71763);let s={},r=t.createContext(s);function o(e){let n=t.useContext(r);return t.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}},87622(e,n,i){i.d(n,{A:()=>o});var t=i(71763),s=i(37773),r=i(91987);function o({term:e,definition:n,abbreviation:i,routePath:a="/glossary",children:l}){let[d,c]=(0,t.useState)(!1),[h,m]=(0,t.useState)(null),[u,p]=(0,t.useState)("top"),x=(0,t.useRef)(null),g=(0,t.useRef)(null),j=(0,t.useCallback)(()=>{let e;if(!x.current||!g.current)return;let n=x.current.getBoundingClientRect(),i=g.current.getBoundingClientRect(),t=window.innerWidth,s=window.innerHeight,r=document.querySelector(".navbar"),o=r?r.getBoundingClientRect().bottom:0,a=n.top-o>=i.height+8,l=s-n.bottom>=i.height+8,d=a||!l?"top":"bottom";e="top"===d?n.top-i.height-8:n.bottom+8;let c=n.left+n.width/2-i.width/2;c=Math.max(8,Math.min(c,t-i.width-8)),p(d),m({top:Math.max(o+4,e),left:c})},[]);(0,t.useEffect)(()=>{let e;if(!d)return;let n=requestAnimationFrame(()=>{e=requestAnimationFrame(()=>{j()})}),i=()=>j(),t=()=>j();return window.addEventListener("scroll",i,!0),window.addEventListener("resize",t),()=>{cancelAnimationFrame(n),e&&cancelAnimationFrame(e),window.removeEventListener("scroll",i,!0),window.removeEventListener("resize",t)}},[d,j]);let f=(0,s.P_)("docusaurus-plugin-glossary"),v=(0,t.useMemo)(()=>{if(n&&"string"==typeof n&&n.length>0)return n;let i=(f&&f.terms||[]).find(n=>"string"==typeof n.term&&n.term.toLowerCase()===String(e).toLowerCase());return i&&i.definition?i.definition:void 0},[n,f,e]),w=(0,t.useMemo)(()=>{let n=i;if(!n){let i=(f&&f.terms||[]).find(n=>"string"==typeof n.term&&n.term.toLowerCase()===String(e).toLowerCase());n=i&&i.abbreviation}if("string"!=typeof n)return;let t=n.trim();if(t&&t.toLowerCase()!==String(e).toLowerCase())return t},[i,f,e]),b=(0,t.useMemo)(()=>a&&"string"==typeof a&&a.length>0?a:f&&f.routePath||"/glossary",[f,a]),y=l||e,C=e.toLowerCase().replace(/\s+/g,"-");return(0,r.jsxs)("span",{ref:x,className:"glossaryTermWrapper_ud7W",children:[(0,r.jsx)("a",{href:`${b}#${C}`,className:"glossaryTerm_x2nJ",onMouseEnter:()=>c(!0),onMouseLeave:()=>c(!1),onFocus:()=>c(!0),onBlur:()=>c(!1),"aria-describedby":`tooltip-${C}`,children:y}),v&&(0,r.jsxs)("span",{ref:g,id:`tooltip-${C}`,className:`tooltip_WjgA ${d?"tooltipVisible_AjfD":""} ${"top"===u?"tooltipTop_uMN4":"tooltipBottom_U9P5"} tooltipFloating_nLk7`,role:"tooltip",style:d&&h?{top:`${h.top}px`,left:`${h.left}px`}:void 0,children:[(0,r.jsx)("strong",{children:e}),w?` (${w}). `:"",v]})]})}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.