[{"data":1,"prerenderedAt":1321},["ShallowReactive",2],{"docs-nav-docs_en":3,"docs-page-\u002Fen\u002Fexamples\u002Ftcp-server-modbus-slave":367,"docs-surround-\u002Fen\u002Fexamples\u002Ftcp-server-modbus-slave":1318},[4],{"title":5,"path":6,"stem":7,"children":8},"En","\u002Fen","en",[9,13,41,58,76,103,157,171,190,211,238,283,303],{"title":10,"path":6,"stem":11,"navTitle":12},"QInsight Documentation","en\u002Findex","Overview",{"title":14,"navTitle":15,"path":16,"stem":17,"children":18,"page":40},"Getting Started",null,"\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[19,23,27,31,36],{"title":20,"path":21,"stem":22,"navTitle":20},"What is QENEX Suite","\u002Fen\u002Fgetting-started\u002Fwhat-is-qenex-suite","en\u002F01.getting-started\u002F1.what-is-qenex-suite",{"title":24,"path":25,"stem":26,"navTitle":24},"What is QInsight","\u002Fen\u002Fgetting-started\u002Fwhat-is-qinsight","en\u002F01.getting-started\u002F2.what-is-qinsight",{"title":28,"path":29,"stem":30,"navTitle":28},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F3.installation",{"title":32,"path":33,"stem":34,"navTitle":35},"The QInsight user interface","\u002Fen\u002Fgetting-started\u002Fthe-qinsight-interface","en\u002F01.getting-started\u002F4.the-qinsight-interface","User interface",{"title":37,"path":38,"stem":39,"navTitle":37},"Licensing","\u002Fen\u002Fgetting-started\u002Flicensing","en\u002F01.getting-started\u002F5.licensing",false,{"title":42,"navTitle":15,"path":43,"stem":44,"children":45,"page":40},"First Project","\u002Fen\u002Ffirst-project","en\u002F02.first-project",[46,50,54],{"title":47,"path":48,"stem":49,"navTitle":47},"Create a project","\u002Fen\u002Ffirst-project\u002Fcreate-a-project","en\u002F02.first-project\u002F1.create-a-project",{"title":51,"path":52,"stem":53,"navTitle":51},"Project structure","\u002Fen\u002Ffirst-project\u002Fproject-structure","en\u002F02.first-project\u002F2.project-structure",{"title":55,"path":56,"stem":57,"navTitle":55},"Project password","\u002Fen\u002Ffirst-project\u002Fproject-password","en\u002F02.first-project\u002F3.project-password",{"title":59,"navTitle":15,"path":60,"stem":61,"children":62,"page":40},"Connecting a Device","\u002Fen\u002Fconnecting-a-device","en\u002F03.connecting-a-device",[63,67,71],{"title":64,"path":65,"stem":66,"navTitle":64},"Add a driver","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-driver","en\u002F03.connecting-a-device\u002F1.add-a-driver",{"title":68,"path":69,"stem":70,"navTitle":68},"Add a protocol","\u002Fen\u002Fconnecting-a-device\u002Fadd-a-protocol","en\u002F03.connecting-a-device\u002F2.add-a-protocol",{"title":72,"path":73,"stem":74,"navTitle":75},"Link a driver and a protocol","\u002Fen\u002Fconnecting-a-device\u002Flink-driver-and-protocol","en\u002F03.connecting-a-device\u002F3.link-driver-and-protocol","Linking",{"title":77,"navTitle":15,"path":78,"stem":79,"children":80,"page":40},"Variables","\u002Fen\u002Fvariables","en\u002F04.variables",[81,85,90,94,99],{"title":82,"path":83,"stem":84,"navTitle":82},"What is a variable","\u002Fen\u002Fvariables\u002Fwhat-is-a-variable","en\u002F04.variables\u002F1.what-is-a-variable",{"title":86,"path":87,"stem":88,"navTitle":89},"Conversion and presentation","\u002Fen\u002Fvariables\u002Fconversion-and-presentation","en\u002F04.variables\u002F2.conversion-and-presentation","Conversion & presentation",{"title":91,"path":92,"stem":93,"navTitle":91},"Add a variable","\u002Fen\u002Fvariables\u002Fadd-a-variable","en\u002F04.variables\u002F3.add-a-variable",{"title":95,"path":96,"stem":97,"navTitle":98},"Matrix variable (array, curve, map)","\u002Fen\u002Fvariables\u002Fmatrix-variable","en\u002F04.variables\u002F4.matrix-variable","Matrix variable",{"title":100,"path":101,"stem":102,"navTitle":100},"Events","\u002Fen\u002Fvariables\u002Fevents","en\u002F04.variables\u002F5.events",{"title":104,"navTitle":15,"path":105,"stem":106,"children":107,"page":40},"Visualization","\u002Fen\u002Fvisualization","en\u002F05.visualization",[108,113,118,122,127,132,137,142,147,152],{"title":109,"path":110,"stem":111,"navTitle":112},"Create a workspace","\u002Fen\u002Fvisualization\u002Fcreate-a-workspace","en\u002F05.visualization\u002F1.create-a-workspace","Workspace",{"title":114,"path":115,"stem":116,"navTitle":117},"Writing values to the device","\u002Fen\u002Fvisualization\u002Fwrite-to-device","en\u002F05.visualization\u002F10.write-to-device","Writing to the device",{"title":119,"path":120,"stem":121,"navTitle":119},"Add a control","\u002Fen\u002Fvisualization\u002Fadd-a-control","en\u002F05.visualization\u002F2.add-a-control",{"title":123,"path":124,"stem":125,"navTitle":126},"Bind a control to a variable","\u002Fen\u002Fvisualization\u002Fbind-a-control","en\u002F05.visualization\u002F3.bind-a-control","Bind a control",{"title":128,"path":129,"stem":130,"navTitle":131},"Graph — signal time course","\u002Fen\u002Fvisualization\u002Fgraph-control","en\u002F05.visualization\u002F4.graph-control","Graph",{"title":133,"path":134,"stem":135,"navTitle":136},"XY Graph — signal versus signal","\u002Fen\u002Fvisualization\u002Fxy-graph-control","en\u002F05.visualization\u002F5.xy-graph-control","XY Graph",{"title":138,"path":139,"stem":140,"navTitle":141},"Gauge — instantaneous value indicator","\u002Fen\u002Fvisualization\u002Fgauge-control","en\u002F05.visualization\u002F6.gauge-control","Gauge",{"title":143,"path":144,"stem":145,"navTitle":146},"Single-Signal — a value with a caption","\u002Fen\u002Fvisualization\u002Fsignal-control","en\u002F05.visualization\u002F7.signal-control","Single-Signal",{"title":148,"path":149,"stem":150,"navTitle":151},"Watch Table — a table of variables","\u002Fen\u002Fvisualization\u002Fwatch-table-control","en\u002F05.visualization\u002F8.watch-table-control","Watch Table",{"title":153,"path":154,"stem":155,"navTitle":156},"Matrix control — maps and calibration","\u002Fen\u002Fvisualization\u002Fmatrix-control","en\u002F05.visualization\u002F9.matrix-control","Matrix control",{"title":158,"navTitle":15,"path":159,"stem":160,"children":161,"page":40},"Running and Monitoring","\u002Fen\u002Frunning","en\u002F06.running",[162,166],{"title":163,"path":164,"stem":165,"navTitle":163},"Start and stop","\u002Fen\u002Frunning\u002Fstart-and-stop","en\u002F06.running\u002F1.start-and-stop",{"title":167,"path":168,"stem":169,"navTitle":170},"Watching live data","\u002Fen\u002Frunning\u002Fwatching-live-data","en\u002F06.running\u002F2.watching-live-data","Live data",{"title":172,"navTitle":15,"path":173,"stem":174,"children":175,"page":40},"Logging and Replay","\u002Fen\u002Flogging-and-replay","en\u002F07.logging-and-replay",[176,180,185],{"title":177,"path":178,"stem":179,"navTitle":177},"Logging data","\u002Fen\u002Flogging-and-replay\u002Flogging-data","en\u002F07.logging-and-replay\u002F1.logging-data",{"title":181,"path":182,"stem":183,"navTitle":184},"Replaying a log","\u002Fen\u002Flogging-and-replay\u002Freplaying-a-log","en\u002F07.logging-and-replay\u002F2.replaying-a-log","Replay",{"title":186,"path":187,"stem":188,"navTitle":189},"Exporting data","\u002Fen\u002Flogging-and-replay\u002Fexporting-data","en\u002F07.logging-and-replay\u002F3.exporting-data","Export",{"title":191,"navTitle":15,"path":192,"stem":193,"children":194,"page":40},"Python Scripts","\u002Fen\u002Fpython-scripts","en\u002F08.python-scripts",[195,199,203,207],{"title":196,"path":197,"stem":198,"navTitle":12},"Scripts overview","\u002Fen\u002Fpython-scripts\u002Fscripts-overview","en\u002F08.python-scripts\u002F1.scripts-overview",{"title":200,"path":201,"stem":202,"navTitle":200},"Accessing variables","\u002Fen\u002Fpython-scripts\u002Faccessing-variables","en\u002F08.python-scripts\u002F2.accessing-variables",{"title":204,"path":205,"stem":206,"navTitle":204},"Example script","\u002Fen\u002Fpython-scripts\u002Fexample-script","en\u002F08.python-scripts\u002F3.example-script",{"title":208,"path":209,"stem":210,"navTitle":208},"CSV post-processing","\u002Fen\u002Fpython-scripts\u002Fcsv-post-processing","en\u002F08.python-scripts\u002F4.csv-post-processing",{"title":212,"navTitle":15,"path":213,"stem":214,"children":215,"page":40},"Custom extensions","\u002Fen\u002Fcustom-extensions","en\u002F09.custom-extensions",[216,220,224,228,233],{"title":217,"path":218,"stem":219,"navTitle":217},"Custom driver","\u002Fen\u002Fcustom-extensions\u002Fcustom-driver","en\u002F09.custom-extensions\u002F1.custom-driver",{"title":221,"path":222,"stem":223,"navTitle":221},"Custom protocol","\u002Fen\u002Fcustom-extensions\u002Fcustom-protocol","en\u002F09.custom-extensions\u002F2.custom-protocol",{"title":225,"path":226,"stem":227,"navTitle":225},"Custom Control","\u002Fen\u002Fcustom-extensions\u002Fcustom-control","en\u002F09.custom-extensions\u002F3.custom-control",{"title":229,"path":230,"stem":231,"navTitle":232},"Complete example — ISS position","\u002Fen\u002Fcustom-extensions\u002Fiss-example","en\u002F09.custom-extensions\u002F4.iss-example","Example ISS",{"title":234,"path":235,"stem":236,"navTitle":237},"Complete example — temperature sensor","\u002Fen\u002Fcustom-extensions\u002Ftemp-sensor-example","en\u002F09.custom-extensions\u002F5.temp-sensor-example","Example temp sensor",{"title":239,"navTitle":15,"path":240,"stem":241,"children":242,"page":40},"QFW SDK","\u002Fen\u002Fdevice-sdk","en\u002F10.device-sdk",[243,248,253,258,263,268,273,278],{"title":244,"path":245,"stem":246,"navTitle":247},"QFW SDK — introduction","\u002Fen\u002Fdevice-sdk\u002Fintroduction","en\u002F10.device-sdk\u002F1.introduction","Introduction",{"title":249,"path":250,"stem":251,"navTitle":252},"XCP in the QFW SDK","\u002Fen\u002Fdevice-sdk\u002Fxcp","en\u002F10.device-sdk\u002F2.xcp","XCP",{"title":254,"path":255,"stem":256,"navTitle":257},"Integration step by step: XCP on TCP with FreeRTOS + lwIP","\u002Fen\u002Fdevice-sdk\u002Fintegration-tcp","en\u002F10.device-sdk\u002F3.integration-tcp","Integration: XCP on TCP",{"title":259,"path":260,"stem":261,"navTitle":262},"XCP on classic CAN — what changes","\u002Fen\u002Fdevice-sdk\u002Fcan","en\u002F10.device-sdk\u002F4.can","XCP on classic CAN",{"title":264,"path":265,"stem":266,"navTitle":267},"Integration without an RTOS: XCP on TCP from the main loop","\u002Fen\u002Fdevice-sdk\u002Fbaremetal","en\u002F10.device-sdk\u002F5.baremetal","Integration without an RTOS",{"title":269,"path":270,"stem":271,"navTitle":272},"The engine contract","\u002Fen\u002Fdevice-sdk\u002Fengine-contract","en\u002F10.device-sdk\u002F6.engine-contract","Engine contract",{"title":274,"path":275,"stem":276,"navTitle":277},"Variable addresses for QInsight","\u002Fen\u002Fdevice-sdk\u002Fvariable-addresses","en\u002F10.device-sdk\u002F7.variable-addresses","Variable addresses",{"title":279,"path":280,"stem":281,"navTitle":282},"Troubleshooting the SDK integration","\u002Fen\u002Fdevice-sdk\u002Ftroubleshooting","en\u002F10.device-sdk\u002F8.troubleshooting","Troubleshooting",{"title":284,"navTitle":15,"path":285,"stem":286,"children":287,"page":40},"Reference","\u002Fen\u002Freference","en\u002F11.reference",[288,292,296,300],{"title":289,"path":290,"stem":291,"navTitle":289},"Drivers","\u002Fen\u002Freference\u002Fdrivers","en\u002F11.reference\u002F1.drivers",{"title":293,"path":294,"stem":295,"navTitle":293},"Protocols","\u002Fen\u002Freference\u002Fprotocols","en\u002F11.reference\u002F2.protocols",{"title":297,"path":298,"stem":299,"navTitle":297},"Controls","\u002Fen\u002Freference\u002Fcontrols","en\u002F11.reference\u002F3.controls",{"title":282,"path":301,"stem":302,"navTitle":282},"\u002Fen\u002Freference\u002Ftroubleshooting","en\u002F11.reference\u002F4.troubleshooting",{"title":304,"navTitle":15,"path":305,"stem":306,"children":307,"page":40},"Examples","\u002Fen\u002Fexamples","en\u002F12.examples",[308,312,317,322,327,331,335,339,343,347,352,357,362],{"title":309,"path":310,"stem":311,"navTitle":309},"Simulation: all signals","\u002Fen\u002Fexamples\u002Fsimulation-all-signals","en\u002F12.examples\u002F01.simulation-all-signals",{"title":313,"path":314,"stem":315,"navTitle":316},"Modbus RTU master over a serial line","\u002Fen\u002Fexamples\u002Fserial-modbus-master","en\u002F12.examples\u002F02.serial-modbus-master","Modbus RTU master",{"title":318,"path":319,"stem":320,"navTitle":321},"Modbus RTU slave with simulated sensors","\u002Fen\u002Fexamples\u002Fserial-modbus-slave","en\u002F12.examples\u002F03.serial-modbus-slave","Modbus RTU slave",{"title":323,"path":324,"stem":325,"navTitle":326},"Modbus TCP master over a TCP client","\u002Fen\u002Fexamples\u002Ftcp-client-modbus-master","en\u002F12.examples\u002F04.tcp-client-modbus-master","Modbus TCP master",{"title":328,"path":329,"stem":330,"navTitle":328},"Modbus TCP slave on the TCP Server","\u002Fen\u002Fexamples\u002Ftcp-server-modbus-slave","en\u002F12.examples\u002F05.tcp-server-modbus-slave",{"title":332,"path":333,"stem":334,"navTitle":332},"Bit field and a script","\u002Fen\u002Fexamples\u002Fbit-field-script","en\u002F12.examples\u002F08.bit-field-script",{"title":336,"path":337,"stem":338,"navTitle":336},"Two ECUs at once","\u002Fen\u002Fexamples\u002Ftwo-ecus","en\u002F12.examples\u002F09.two-ecus",{"title":340,"path":341,"stem":342,"navTitle":340},"ISS position live","\u002Fen\u002Fexamples\u002Fiss-live-tracking","en\u002F12.examples\u002F10.iss-live-tracking",{"title":344,"path":345,"stem":346,"navTitle":344},"Simulated thermometer","\u002Fen\u002Fexamples\u002Fsimul-temp-measure","en\u002F12.examples\u002F11.simul-temp-measure",{"title":348,"path":349,"stem":350,"navTitle":351},"JSON signals from a Python generator","\u002Fen\u002Fexamples\u002Fjson-signal-python","en\u002F12.examples\u002F12.json-signal-python","JSON signals from Python",{"title":353,"path":354,"stem":355,"navTitle":356},"Raw CAN frames from a Raspberry Pi","\u002Fen\u002Fexamples\u002Fraw-can-python","en\u002F12.examples\u002F13.raw-can-python","Raw CAN from a Raspberry Pi",{"title":358,"path":359,"stem":360,"navTitle":361},"XCP on TCP on a NUCLEO-H723ZG: measurement, stimulation and calibration maps","\u002Fen\u002Fexamples\u002Ftcp-client-xcp-nucleo-maps","en\u002F12.examples\u002F14.tcp-client-xcp-nucleo-maps","XCP on TCP on NUCLEO-H723ZG",{"title":363,"path":364,"stem":365,"navTitle":366},"XCP on CAN on a NUCLEO-H723ZG: measurement, stimulation and calibration maps","\u002Fen\u002Fexamples\u002Fcan-xcp-nucleo-maps","en\u002F12.examples\u002F15.can-xcp-nucleo-maps","XCP on CAN on NUCLEO-H723ZG",{"id":368,"title":328,"body":369,"description":1313,"extension":1314,"meta":1315,"navTitle":328,"navigation":974,"path":329,"seo":1316,"stem":330,"__hash__":1317},"docs_en\u002Fen\u002F12.examples\u002F05.tcp-server-modbus-slave.md",{"type":370,"value":371,"toc":1301},"minimark",[372,376,385,390,418,431,435,508,512,517,520,533,629,641,695,712,715,842,880,888,892,895,922,1006,1019,1138,1156,1159,1165,1190,1194,1231,1235,1297],[373,374,328],"h1",{"id":375},"modbus-tcp-slave-on-the-tcp-server",[377,378,379,380,384],"p",{},"You will find the project in\n",[381,382,383],"code",{},"Examples\\Qenex_TcpServer_ModbusSlave_HoldingRegisters.qproj"," in the\nExamples folder next to QInsight.exe.",[386,387,389],"h2",{"id":388},"what-the-example-shows","What the example shows",[377,391,392,393,397,398,401,402,405,406,409,410,413,414,417],{},"Here QInsight is ",[394,395,396],"strong",{},"not the master but the slave",": the ",[394,399,400],{},"TCP Server","\ndriver listens on port 502 and the ",[394,403,404],{},"Modbus Slave (RTU\u002FTCP)"," protocol in\n",[381,407,408],{},"tcp"," mode serves two variables as holding registers 0 and 1 under unit\naddress 2. There is no real device — the register values are produced by\na periodic Python script that every 2 s moves a simulated ",[394,411,412],{},"oil\ntemperature"," (0–150 °C) and ",[394,415,416],{},"oil pressure"," (1000–2500 kPa) one step up\nor down. An external Modbus TCP master connecting to QInsight reads the\nsaw-tooth rising and falling values.",[377,419,420,421,424,425,430],{},"The other half of the example is the display: a script write into a\nvariable of a device protocol does not show in controls (no signal sample\nis born). The script therefore writes every value ",[394,422,423],{},"twice"," — into the\nslave variable for the master and into a\n",[426,427,429],"a",{"href":428},"\u002Freference\u002Fprotocols#virtual-variables","virtual variable"," drawn by the\ngraph and the signal controls. The project also shows how the TCP Server\nbehaves when the client drops out: a pulled cable is detected by the\nkeepalive, the server returns to listening and the master reconnects once\nthe link is back.",[386,432,434],{"id":433},"what-you-need","What you need",[436,437,438,450,483,493,500],"ul",{},[439,440,441,444,445,449],"li",{},[394,442,443],{},"QInsight with Python set up"," — the scripts are the core of the\nexample, see ",[426,446,448],{"href":447},"\u002Fpython-scripts\u002Fscripts-overview#python-setup","Python setup",".",[439,451,452,453,455,456,459,460,463,464,467,468,471,472,475,476,478,479,482],{},"A ",[394,454,326],{}," as the counterpart, for example ",[394,457,458],{},"qModMaster",".\nPoint it at the IP address of the QInsight PC, port ",[394,461,462],{},"502",", unit ",[394,465,466],{},"2",",\nand let it read ",[394,469,470],{},"holding registers"," from address ",[394,473,474],{},"0",", count ",[394,477,466],{},".\nThanks to ",[381,480,481],{},"respondToAnyUnit=true"," the slave answers any unit address as\nwell.",[439,484,485,486,489,490,449],{},"The master may run ",[394,487,488],{},"on the same PC"," — then it connects to ",[381,491,492],{},"127.0.0.1",[439,494,495,496,499],{},"With the master on another computer, the ",[394,497,498],{},"firewall on the QInsight PC","\nmust allow incoming connections on port 502 (local side QInsight,\nremote side the master). After an outage the connection is always\nre-established by the master (the client); the server only listens.",[439,501,502,503,507],{},"Port 502 must not be taken by another program; otherwise the driver\nkeeps retrying to open it (see ",[426,504,506],{"href":505},"\u002Freference\u002Fdrivers#reconnection","Reconnection",")\nand comes up as soon as the port is free.",[386,509,511],{"id":510},"the-project","The project",[513,514,516],"h3",{"id":515},"drivers-and-protocols","Drivers and protocols",[377,518,519],{},"The project has two driver + protocol pairs.",[377,521,522,524,525,528,529,532],{},[394,523,400],{}," (",[381,526,527],{},"TcpServerDriver",") with the settings\n",[381,530,531],{},"bindAddress=0.0.0.0;port=502;reconnectDelayMs=1000;reconnectAttempts=-1;keepAliveMs=5000",":",[534,535,536,552],"table",{},[537,538,539],"thead",{},[540,541,542,546,549],"tr",{},[543,544,545],"th",{},"Parameter",[543,547,548],{},"Value",[543,550,551],{},"Meaning in the example",[553,554,555,571,583,599,612],"tbody",{},[540,556,557,563,566],{},[558,559,560],"td",{},[381,561,562],{},"bindAddress",[558,564,565],{},"0.0.0.0",[558,567,568,569],{},"listens on all interfaces — the master connects through any IP address of the PC as well as ",[381,570,492],{},[540,572,573,578,580],{},[558,574,575],{},[381,576,577],{},"port",[558,579,462],{},[558,581,582],{},"the standard Modbus TCP port",[540,584,585,590,593],{},[558,586,587],{},[381,588,589],{},"reconnectDelayMs",[558,591,592],{},"1000",[558,594,595,596],{},"pause between attempts to ",[394,597,598],{},"open the listening port",[540,600,601,606,609],{},[558,602,603],{},[381,604,605],{},"reconnectAttempts",[558,607,608],{},"-1",[558,610,611],{},"keeps trying to open the port forever (port in use, address not present)",[540,613,614,619,622],{},[558,615,616],{},[381,617,618],{},"keepAliveMs",[558,620,621],{},"5000",[558,623,624,625,628],{},"keepalive on the ",[394,626,627],{},"accepted connection",": probes after 5 s of silence, a dead client is detected within seconds",[377,630,631,632,524,634,637,638,532],{},"Under it ",[394,633,404],{},[381,635,636],{},"ModbusSlaveProtocol",") with the\nsettings ",[381,639,640],{},"mode=tcp;unitId=2;respondToAnyUnit=true",[534,642,643,653],{},[537,644,645],{},[540,646,647,649,651],{},[543,648,545],{},[543,650,548],{},[543,652,551],{},[553,654,655,667,679],{},[540,656,657,662,664],{},[558,658,659],{},[381,660,661],{},"mode",[558,663,408],{},[558,665,666],{},"Modbus TCP framing (MBAP), matching the TCP Server driver",[540,668,669,674,676],{},[558,670,671],{},[381,672,673],{},"unitId",[558,675,466],{},[558,677,678],{},"the slave's own address",[540,680,681,686,689],{},[558,682,683],{},[381,684,685],{},"respondToAnyUnit",[558,687,688],{},"true",[558,690,691,692],{},"the slave answers regardless of the unit address in the request — set explicitly, because the pre-filled template contains ",[381,693,694],{},"false",[377,696,697,698,524,701,704,705,524,708,711],{},"The second pair, ",[394,699,700],{},"Virtual Variables Host",[381,702,703],{},"VirtualDataDriver",") +\n",[394,706,707],{},"Virtual Variables",[381,709,710],{},"VirtualDataProtocol","), has no settings; it carries\nthe display copies of both registers.",[513,713,77],{"id":714},"variables",[534,716,717,739],{},[537,718,719],{},[540,720,721,724,727,730,733,736],{},[543,722,723],{},"Variable",[543,725,726],{},"Namespace",[543,728,729],{},"Type",[543,731,732],{},"Protocol",[543,734,735],{},"Comm params",[543,737,738],{},"Role",[553,740,741,770,795,821],{},[540,742,743,748,753,756,759,764],{},[558,744,745],{},[381,746,747],{},"OilTemp",[558,749,750],{},[381,751,752],{},"\u002FModbus",[558,754,755],{},"ushort",[558,757,758],{},"Modbus Slave",[558,760,761],{},[381,762,763],{},"registerType=\"holdingRegister\";address=\"0\";wordOrder=\"big\";direction=\"read\"",[558,765,766,769],{},[394,767,768],{},"holding register 0"," read by the master",[540,771,772,777,781,783,785,790],{},[558,773,774],{},[381,775,776],{},"OilPressure",[558,778,779],{},[381,780,752],{},[558,782,755],{},[558,784,758],{},[558,786,787],{},[381,788,789],{},"registerType=\"holdingRegister\";address=\"1\";wordOrder=\"big\";direction=\"read\"",[558,791,792,769],{},[394,793,794],{},"holding register 1",[540,796,797,802,807,810,812,815],{},[558,798,799],{},[381,800,801],{},"OilTempView",[558,803,804],{},[381,805,806],{},"\u002FVirtual",[558,808,809],{},"double",[558,811,707],{},[558,813,814],{},"—",[558,816,817,818,820],{},"display copy of ",[381,819,747],{}," for the graph and the signal control",[540,822,823,828,832,834,836,838],{},[558,824,825],{},[381,826,827],{},"OilPressureView",[558,829,830],{},[381,831,806],{},[558,833,809],{},[558,835,707],{},[558,837,814],{},[558,839,817,840,820],{},[381,841,776],{},[377,843,844,845,847,848,851,852,855,856,859,860,863,864,867,868,871,872,875,876,879],{},"The slave variables are ",[381,846,755],{}," — a single 16-bit register, into which\nboth ranges 0–150 and 1000–2500 fit without scaling. The presentations\n",[381,849,850],{},"Temperature"," (0–150, ",[381,853,854],{},"°C",") and ",[381,857,858],{},"Pressure"," (1000–2500, ",[381,861,862],{},"kPa",") both use the\nlinear conversion ",[381,865,866],{},"Raw"," with ",[381,869,870],{},"multiplier=1",", ",[381,873,874],{},"offset=0"," and the format\n",[381,877,878],{},"{0:F0}","; the engineering value equals the raw one, so the master reads\ndegrees and kilopascals directly. The virtual copies share the same\npresentations, so the graph and the signal controls show the same units\nand ranges.",[377,881,882,883,887],{},"None of the slave variables is bound to a control — since a\n",[426,884,886],{"href":885},"\u002Fpython-scripts\u002Faccessing-variables#writing-vs-displaying-virtual-variables","script write on a device protocol raises no UI event",",\nit would show nothing there.",[513,889,891],{"id":890},"scripts","Scripts",[377,893,894],{},"The project has two scripts, both for runtime only (not for replay),\nblocking, without a timeout.",[377,896,897,900,901,904,905,908,909,912,913,916,917,921],{},[381,898,899],{},"init.py"," in ",[394,902,903],{},"Startup"," mode sets the initial state of the simulation and\nwrites the starting values right away. The Python globals ",[381,906,907],{},"oil_temp",",\n",[381,910,911],{},"oil_pressure"," and ",[381,914,915],{},"direction"," live in the\n",[426,918,920],{"href":919},"\u002Fpython-scripts\u002Faccessing-variables#shared-script-scope","shared script scope",",\nso the periodic script finds them:",[923,924,929],"pre",{"className":925,"code":926,"language":927,"meta":928,"style":928},"language-python shiki shiki-themes github-light github-dark-default","# Startup script: initial state of the simulated sensors.\n# The periodic script (simulate.py) ramps the values from here; the globals persist\n# between script runs inside one runtime session.\noil_temp = 0.0          # degC, ramps 0 .. 150\noil_pressure = 1000.0   # kPa, ramps 1000 .. 2500\ndirection = 1           # +1 ramping up, -1 ramping down\n\n# Publish the initial values right away, both to the slave registers and to the display copies.\nOilTemp.EngValue = oil_temp\nOilPressure.EngValue = oil_pressure\nOilTempView.EngValue = oil_temp\nOilPressureView.EngValue = oil_pressure\n","python","",[381,930,931,939,945,951,957,963,969,976,982,988,994,1000],{"__ignoreMap":928},[932,933,936],"span",{"class":934,"line":935},"line",1,[932,937,938],{},"# Startup script: initial state of the simulated sensors.\n",[932,940,942],{"class":934,"line":941},2,[932,943,944],{},"# The periodic script (simulate.py) ramps the values from here; the globals persist\n",[932,946,948],{"class":934,"line":947},3,[932,949,950],{},"# between script runs inside one runtime session.\n",[932,952,954],{"class":934,"line":953},4,[932,955,956],{},"oil_temp = 0.0          # degC, ramps 0 .. 150\n",[932,958,960],{"class":934,"line":959},5,[932,961,962],{},"oil_pressure = 1000.0   # kPa, ramps 1000 .. 2500\n",[932,964,966],{"class":934,"line":965},6,[932,967,968],{},"direction = 1           # +1 ramping up, -1 ramping down\n",[932,970,972],{"class":934,"line":971},7,[932,973,975],{"emptyLinePlaceholder":974},true,"\n",[932,977,979],{"class":934,"line":978},8,[932,980,981],{},"# Publish the initial values right away, both to the slave registers and to the display copies.\n",[932,983,985],{"class":934,"line":984},9,[932,986,987],{},"OilTemp.EngValue = oil_temp\n",[932,989,991],{"class":934,"line":990},10,[932,992,993],{},"OilPressure.EngValue = oil_pressure\n",[932,995,997],{"class":934,"line":996},11,[932,998,999],{},"OilTempView.EngValue = oil_temp\n",[932,1001,1003],{"class":934,"line":1002},12,[932,1004,1005],{},"OilPressureView.EngValue = oil_pressure\n",[377,1007,1008,900,1011,1014,1015,1018],{},[381,1009,1010],{},"simulate.py",[394,1012,1013],{},"Periodic"," mode with the parameters ",[381,1016,1017],{},"period=2;unit=s","\nmoves the temperature by 1 °C and the pressure by 10 kPa every 2 s; at\nthe upper or lower bound it clamps both quantities to the end value and\nflips the direction. Both ranges have 150 steps, so one sweep up takes\n5 minutes:",[923,1020,1022],{"className":925,"code":1021,"language":927,"meta":928,"style":928},"# Periodic script (period=2;unit=s): saw-tooth ramp of the simulated sensors.\n# Temperature moves 1 degC per step between 0 and 150, pressure 10 kPa per step between\n# 1000 and 2500, so one sweep up takes 5 minutes; at either end the direction flips.\n#\n# Every value is written twice on purpose:\n#  - OilTemp \u002F OilPressure are the Modbus slave variables. The slave serves their current\n#    value to the master (holding registers 0 and 1). A script write never raises a UI event\n#    on a device protocol, so these two are not shown in any control.\n#  - OilTempView \u002F OilPressureView are virtual variables. The Virtual Data protocol publishes\n#    every script write to the UI, so the graph and signal controls follow them.\noil_temp += direction * 1.0\noil_pressure += direction * 10.0\n\nif oil_temp >= 150.0 or oil_pressure >= 2500.0:\n    oil_temp, oil_pressure, direction = 150.0, 2500.0, -1\nelif oil_temp \u003C= 0.0 or oil_pressure \u003C= 1000.0:\n    oil_temp, oil_pressure, direction = 0.0, 1000.0, 1\n\nOilTemp.EngValue = oil_temp\nOilPressure.EngValue = oil_pressure\nOilTempView.EngValue = oil_temp\nOilPressureView.EngValue = oil_pressure\n",[381,1023,1024,1029,1034,1039,1044,1049,1054,1059,1064,1069,1074,1079,1084,1089,1095,1101,1107,1113,1118,1123,1128,1133],{"__ignoreMap":928},[932,1025,1026],{"class":934,"line":935},[932,1027,1028],{},"# Periodic script (period=2;unit=s): saw-tooth ramp of the simulated sensors.\n",[932,1030,1031],{"class":934,"line":941},[932,1032,1033],{},"# Temperature moves 1 degC per step between 0 and 150, pressure 10 kPa per step between\n",[932,1035,1036],{"class":934,"line":947},[932,1037,1038],{},"# 1000 and 2500, so one sweep up takes 5 minutes; at either end the direction flips.\n",[932,1040,1041],{"class":934,"line":953},[932,1042,1043],{},"#\n",[932,1045,1046],{"class":934,"line":959},[932,1047,1048],{},"# Every value is written twice on purpose:\n",[932,1050,1051],{"class":934,"line":965},[932,1052,1053],{},"#  - OilTemp \u002F OilPressure are the Modbus slave variables. The slave serves their current\n",[932,1055,1056],{"class":934,"line":971},[932,1057,1058],{},"#    value to the master (holding registers 0 and 1). A script write never raises a UI event\n",[932,1060,1061],{"class":934,"line":978},[932,1062,1063],{},"#    on a device protocol, so these two are not shown in any control.\n",[932,1065,1066],{"class":934,"line":984},[932,1067,1068],{},"#  - OilTempView \u002F OilPressureView are virtual variables. The Virtual Data protocol publishes\n",[932,1070,1071],{"class":934,"line":990},[932,1072,1073],{},"#    every script write to the UI, so the graph and signal controls follow them.\n",[932,1075,1076],{"class":934,"line":996},[932,1077,1078],{},"oil_temp += direction * 1.0\n",[932,1080,1081],{"class":934,"line":1002},[932,1082,1083],{},"oil_pressure += direction * 10.0\n",[932,1085,1087],{"class":934,"line":1086},13,[932,1088,975],{"emptyLinePlaceholder":974},[932,1090,1092],{"class":934,"line":1091},14,[932,1093,1094],{},"if oil_temp >= 150.0 or oil_pressure >= 2500.0:\n",[932,1096,1098],{"class":934,"line":1097},15,[932,1099,1100],{},"    oil_temp, oil_pressure, direction = 150.0, 2500.0, -1\n",[932,1102,1104],{"class":934,"line":1103},16,[932,1105,1106],{},"elif oil_temp \u003C= 0.0 or oil_pressure \u003C= 1000.0:\n",[932,1108,1110],{"class":934,"line":1109},17,[932,1111,1112],{},"    oil_temp, oil_pressure, direction = 0.0, 1000.0, 1\n",[932,1114,1116],{"class":934,"line":1115},18,[932,1117,975],{"emptyLinePlaceholder":974},[932,1119,1121],{"class":934,"line":1120},19,[932,1122,987],{},[932,1124,1126],{"class":934,"line":1125},20,[932,1127,993],{},[932,1129,1131],{"class":934,"line":1130},21,[932,1132,999],{},[932,1134,1136],{"class":934,"line":1135},22,[932,1137,1005],{},[377,1139,1140,1141,1144,1145,912,1147,1149,1150,1152,1153,1155],{},"The ",[394,1142,1143],{},"double write"," is deliberate and is the key to the whole example.\nThe write into ",[381,1146,747],{},[381,1148,776],{}," only stores the value that the\nModbus Slave hands to the master on its next request — a device protocol\nproduces no UI sample from such a write. The write into ",[381,1151,801],{}," and\n",[381,1154,827],{},", on the other hand, is published by the Virtual\nVariables protocol as a sample timestamped at the moment of the write,\nand that is what the graph and the signal controls see. If the script\nwrote only the slave variables, the master would read correct data but\nthe workspace would stay empty; if it wrote only the virtual ones,\neverything would be displayed but the master would read zeros.",[513,1157,112],{"id":1158},"workspace",[377,1160,1140,1161,1164],{},[394,1162,1163],{},"Simulated sensors"," workspace holds three controls, all bound to the\nvirtual copies:",[436,1166,1167,1178],{},[439,1168,452,1169,1171,1172,1174,1175,1177],{},[394,1170,131],{}," \"Simulated sensors (virtual copies of the slave registers)\"\nwith a 300 s time window (exactly one ramp sweep) and two vertical axes\nwith fixed ranges: left 0–150 for ",[381,1173,801],{}," (red), right 1000–2500\nfor ",[381,1176,827],{}," (blue).",[439,1179,1180,1181,1184,1185,1152,1187,1189],{},"Two ",[394,1182,1183],{},"Signal"," controls (250 ms refresh) for ",[381,1186,801],{},[381,1188,827],{},", read-only.",[386,1191,1193],{"id":1192},"what-you-will-see-and-what-to-try","What you will see and what to try",[1195,1196,1197,1200,1203,1221,1224],"ol",{},[439,1198,1199],{},"Start the runtime. The graph starts drawing two saw-tooth curves: the\ntemperature from 0 °C upwards, the pressure from 1000 kPa upwards;\nafter 5 minutes both turn around.",[439,1201,1202],{},"Connect the master to port 502, unit 2, and read holding registers 0\nand 1. The master shows the same values as the signal controls and\nevery 2 s they move by 1 and by 10. The slave only serves the values;\nbetween requests the master sends nothing and the driver does not treat\nthe silence as a fault.",[439,1204,1205,1208,1209,1212,1213,1216,1217,1220],{},[394,1206,1207],{},"Pull the master's cable"," (or disconnect its network). After 5 s of\nsilence the keepalive starts probing and a few seconds later the\n",[394,1210,1211],{},"Logs"," window shows the warning ",[381,1214,1215],{},"client … lost",". The server returns\nto listening and the driver stays running; a clean disconnect of the\nmaster would be logged as ",[381,1218,1219],{},"client … disconnected",". The ramp keeps\ngoing — neither the script nor the virtual variables depend on the\nclient.",[439,1222,1223],{},"Plug the cable back in. The master reconnects on its own and reads the\nvalues that kept climbing in the meantime; nothing needs to be done on\nthe QInsight side.",[439,1225,1226,1227,1230],{},"Connect a ",[394,1228,1229],{},"second master"," while the first one still holds its\nconnection: the new incoming connection replaces the current one — the\nTCP Server serves a single client. A dead master is thus replaced by a\nnew one without waiting for the keepalive.",[386,1232,1234],{"id":1233},"related-chapters","Related chapters",[436,1236,1237,1250,1256,1261,1271,1281,1287],{},[439,1238,1239,1152,1242,1244,1245,912,1247,1249],{},[426,1240,400],{"href":1241},"\u002Freference\u002Fdrivers#tcp-server",[426,1243,506],{"href":505}," — driver parameters,\nkeepalive, the ",[381,1246,1215],{},[381,1248,1219],{}," messages.",[439,1251,1252,1255],{},[426,1253,404],{"href":1254},"\u002Freference\u002Fprotocols#modbus-slave-rtutcp"," —\nslave settings, register parameters and behaviour on writes from the\nmaster.",[439,1257,1258,1260],{},[426,1259,707],{"href":428}," — why the\ndisplay goes through virtual copies.",[439,1262,1263,1266,1267,1270],{},[426,1264,200],{"href":1265},"\u002Fpython-scripts\u002Faccessing-variables"," — writing\nthrough ",[381,1268,1269],{},"EngValue"," and the shared script scope.",[439,1272,1273,1276,1277,1280],{},[426,1274,196],{"href":1275},"\u002Fpython-scripts\u002Fscripts-overview"," — the Startup and\nPeriodic modes, the ",[381,1278,1279],{},"period"," parameter.",[439,1282,1283,1286],{},[426,1284,167],{"href":1285},"\u002Frunning\u002Fwatching-live-data#logs-and-script-logs","\n— the Logs and Script-Logs windows.",[439,1288,1289,1152,1293,449],{},[426,1290,1292],{"href":1291},"\u002Fvisualization\u002Fgraph-control","Graphs",[426,1294,1296],{"href":1295},"\u002Fvisualization\u002Fsignal-control","Signal control",[1298,1299,1300],"style",{},"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);}",{"title":928,"searchDepth":947,"depth":947,"links":1302},[1303,1304,1305,1311,1312],{"id":388,"depth":941,"text":389},{"id":433,"depth":941,"text":434},{"id":510,"depth":941,"text":511,"children":1306},[1307,1308,1309,1310],{"id":515,"depth":947,"text":516},{"id":714,"depth":947,"text":77},{"id":890,"depth":947,"text":891},{"id":1158,"depth":947,"text":112},{"id":1192,"depth":941,"text":1193},{"id":1233,"depth":941,"text":1234},"QInsight as a Modbus TCP slave (unit 2) on port 502 — a periodic script simulates oil temperature and pressure into holding registers 0 and 1, read by an external master.","md",{},{"title":328,"description":1313},"7q1-B4HcQWJJt9FgvcG9Wsy2HQfK2fLjd104hOGJgU0",[1319,1320],{"title":323,"path":324,"stem":325,"navTitle":326,"children":-1},{"title":332,"path":333,"stem":334,"navTitle":332,"children":-1},1791554568308]