Help on Conditional for network
-
I'm looking for some advice on making the wifi connection conditional on my Duet2 wifi. My situation is that I have the board set up with a PanelDu and use the wifi connection and DWC for debugging, but I want "normal operation" to be without the wifi. I set up a wifi router for debug, and when this router is not running (normal operation), I get continual messages on the PanelDu that the network is not connected.
My simple idea is that in my config.g, after turning on the network, I check if the network interface state is active. If not, I use a G4 to wait a bit for the connection to be made, then look at the object model again . If the network is still not active, I send an M552 S0 to turn off the network.
When I implemented this, I can't get the network to stay connected, even when the delay is up to 30 seconds. It seems like
So, is my reasoning sound? And to the obvious question - can I post my code? I foolishly left it on the printer in my makerspace and wo'n't get to it until next Tuesday, but I believe it looked like this:
;############################################### ;START OF NETWORKING SETUP ;!## Networking ;! Set up networking parameters. M552 S1 ;! Enable Network M586 P0 S1 ;! Enable HTTP M586 P1 S0 ;! Netmask M586 P2 S0 ;! Disable Telnet if network.interfaces[0].state != "active" ;If the netwokr is not yet active G4 S30 ; wait 30 seconds for it to become active if network.interfaces[0].state != "active" M552 S0 ;END OF NETWORKING SETUP ;###############################################
-
The list of possible states is
network.interfaces[].stateNetwork state
This property may be one of the following:
disabled: Network disabled
enabled: Network enabled but not started yet
starting1: Starting up (used by WiFi networking in standalone mode)
starting2: Starting up (used by WiFi networking in standalone mode)
changingMode: Running and in the process of switching between modes (used by WiFi networking in standalone mode)
establishingLink: Starting up, waiting for link
obtainingIP: Link established, waiting for DHCP
connected: Just established a connection
active: Network runningHave you checked the the state is actually "active" when the board is connected to your wifi?
-
@OwenD Yes I have. If I comment out lines 10-13 in the code above and, power cycle the board and let it connect, then I can echo network.interfaces[0].state and "active" is returned.
-
I did some testing.
It seems that the network connection isn't done until after config.g is finished processing.I used the following code to check.
echo >"myLog.txt" state.upTime, "secs. state:", network.interfaces[0].state, "IP:", network.interfaces[0].actualIP while (network.interfaces[0].state != "active") && (state.upTime < 90) echo >>"myLog.txt" state.upTime, "secs. state:", network.interfaces[0].state, "IP:", network.interfaces[0].actualIP echo >>"myLog.txt" state.upTime, "secs. state:", network.interfaces[0].state, "IP:", network.interfaces[0].actualIP
If the code was anywhere in config.g, then the state remained "disabled" and it would time out, simply filling the file with the same line of text.
After that, the network would connect normally.If I put the code in daemon.g, I got this.
18 secs. state: changingMode IP: 0.0.0.0 18 secs. state: changingMode IP: 0.0.0.0 18 secs. state: changingMode IP: 0.0.0.0 19 secs. state: changingMode IP: 0.0.0.0 19 secs. state: active IP: 192.168.1.163
So if you modify my code and put it in daemon.g you should achieve what you want.
-
@mikeabuilder
In thinking about this I thought you might be able to use whether or not you have a wifi signal and/or whether or not the network was enabled to avoid running the code every time daemon.g is invoked, but in my case the object model does not show a signal value even though it is reported in M122
My idea was to useif (network.interfaces[0].state != "active") && (state.upTime > 90) && (network.interfaces[0].signal < -50) ; or whatever value M552 S0
However the object model doesn't expose whether networking is active (unless the interface becomes null when it's not?)
And I don't get a signal in the object model.
Perhaps @dc42 can commentM122
= WiFi = Network state is active WiFi module is connected to access point Failed messages: pending 0, notready 0, noresp 0 WiFi firmware version 1.27 WiFi MAC address bc:dd:c2:89:a0:bb WiFi Vcc 3.38, reset reason Power up WiFi flash size 4194304, free heap 24352 WiFi IP address 192.168.1.163 WiFi signal strength -52dBm, mode 802.11n, reconnections 0, sleep mode modem Clock register 00002002 Socket states: 0 0 0 0 0 0 0 0
-
@OwenD - that's for your further thoughts on this. I'll, pursue the daemon method. I'll set a global variable in config.g (last line) and use this in an if statement in daemon for enable running the code to look for an active network connection.
global daemon_network_check = 1
Then in daemon.g:
if exists global.daemon_network_check ; needed in case the daemon runs before config.g finishes. if global.daemon_network_check <=3 ;three tries will give the network 30 seconds to connect. I might reduce this after testing. if network.interfaces[0].state = "active" global.daemon_network_check = 99 else if global.daemon_network_check = 3 ; no network after three tries M552 S0 ; disable networking global.daemon_network_check = global.daemon_network_check+1
Maybe I can streamline this some, but that's the general idea.
-
@OwenD said in Help on Conditional for network:
It seems that the network connection isn't done until after config.g is finished processing.
That's correct, RRF waits until the end of config.g before enabling the network, in case there are commands in config.g that change the network parameters.
-
@mikeabuilder
I thought of a hack that would avoid using daemon.g and global variables.
If you're not using daemon.g in a loop, it's doing a disk read every 10 seconds.
Seems pointless for a task that's only ever going to be required at startup and would avoid having network disabled if you lost wifi signal temporarily.At the start of your config.g call this macro to create a runonce.g
M98 P"create_runonce.g"
; create_runonce.g - creates a file that is run after config.g is run and network is enabled echo >"0:/sys/runonce.g" "G4 S20 ; give the network time to establish connection" echo >>"0:/sys/runonce.g" "if network.interfaces[0].state != ""active""" echo >>"0:/sys/runonce.g" " M552 S0 ; disable networking" echo >>"0:/sys/runonce.g" " M291 R""Network check"" P""Disable networking"" S0 T3" echo >>"0:/sys/runonce.g" "else" echo >>"0:/sys/runonce.g" " M291 R""Network check"" P""Network active"" S0 T3"
From the documents
runonce.g
File runonce.g is supported from RRF3.1.0 and later. If this file is present at startup, it is run after running config.g and activating the network, and then deleted. -
@OwenD said in Help on Conditional for network:
If you're not using daemon.g in a loop, it's doing a disk read every 10 seconds.
Seems pointless for a task that's only ever going to be required at startup and would avoid having network disabled if you lost wifi signal temporarily.Once you have determined whether the network us running or not and taken any appropriate action, you can execute e.g.
G1G4 S9999 in a loop in daemon.g to avoid looking at the SD card every 10 seconds. -
Thanks for the comments. I may be asking for more detail than I can fully understand, but I have two questions/comments.
In my proposed code above, the first and second nested if's query the state of a global variable, and the of those will stop execution whether the network is running or not. It either counts counts to the limit and gives up on the network (and the value is set to 4), or the network is alive and the value set to 99. In either case, every time the daemon runs after that, the object model will not be queried. So my question is - does RRF store the value of global variables on the SD card? Also, are the object model variables stored on the SD card? I would have guessed both the object model and global variables are stored in memory.
Second question - @dc42 you offer using G1 S9999 in a loop. I looked at G1 in the gcode dictionary page and don't see a definition that helps me understand this path. It references the S parameter on G1 as pertaining to laser. If tehre is no laser, does this make a G1S9999 a no-op?
-
@mikeabuilder
You are correct in assuming that the OM and globals are stored in memory.
daemon.g normally gets run once every 10 seconds.
Each time it runs, it reads the contents of the macro from the SD card, performs whatever you coded, then exits.To avoid that card read, you can put a while loop in daemon.g so that it never exits.
However you must put a G4 dwell in to hand control back to the main process ( @DC42 made a typo with G1)
The very long dwell fsuggested by DC42 would avoid the constant checking of the if conditions.while true ;do your stuff G4 S9999999 ; not sure the maximum
-
@OwenD thanks for pointing out my typo.
The maximum G4 parameter supported is 2^31 milliseconds (P parameter) so (2^31)/1000 seconds (S parameter).
-
Thanks @OwenD and @dc42, I'll put my new knowledge to the test later today.
It's good to understand that daemon.g always reads the current daemon.g file before running, but this read overhead seems very tiny and will occur in any event - even for my current daemon.g file that only has a comment in it to remind me what the daemon.g file is for.
As the read time is the only downside to the code I put in this thread above, I'm going to implement it and assess the results.
-
Just tested my code and it works very well - after I fixed my typos and syntax errors.