I want to get the frame time (relative) of the first packet that is not communicating on sos and DIS ports and ip address is not the one mentioned in the if statement. But the packet should be utilizing port 24111. However, the code below is not working for this purpose. It works, until I add udp_port~=24111. After that it gives me no results, which means that it doesn't go inside that conditional statement. I have tried to write the condition in multiple ways, even separating it out into a new if statement but it doesn't work. What I am doing wrong here. Thanks for suggestions in advance.
Here is the piece of code that I have at the moment
local first_outpacket = 0
local flag = 0
function stats_first_packet()
local udp_port
local frame_time
local ip_addr
frame_time = time_relative_extractor()
udp_port = udp_port_extractor()
ip_addr = ip_addr_extractor()
if ( udp_port ) then
if (not (udp_port == 3000 or udp_port==3838 or flag==1 or ip_addr=="192.168.1.2" or udp_port~=24111)) then
first_outpacket = frame_time
print(frame_time)
flag = 1
else
-- print("tcp_src_port already recorded")
end
else
-- print("no tcp_src_port")
end
end
The problem apparently lies in the data type returned by the extractor() functions. In order to compare them with another value in the if statement they have to be converted into strings using tostring() function.
For example:
if (not (tostring(udp_port) == "3000" or tostring(udp_port)=="3838" or flag==1))
Related
i want to make this, when the baseFinal is touched by a block (Bloque) it gives you money and the block is destroyed. it gives me an error: attempt to index nil with 'stats'
local base = script.Parent.Base
local baseFinal = script.Parent.Final
local plr = game.Players.LocalPlayer
baseFinal.Touched:Connect(function(hit)
if hit.Name == "Bloque" then
wait(0.6)
plr.stats.Value = plr.stats.Value + 5 // here is the error
hit:Destroy()
end
end)
The error is telling you that the plr variable is undefined or nil.
Since this code is running in a Script, the issue is how you are accessing the Player object. See the documentation for Players.LocalPlayer :
This property is only defined for LocalScripts (and ModuleScripts required by them), as they run on the client. For the server (on which Script objects run their code), this property is nil.
The way to fix this is to access the Player object another way. One way is to connect to the Players.PlayerAdded signal.
local base = script.Parent.Base
local baseFinal = script.Parent.Final
local connections = {}
game.Players.PlayerAdded:Connect( function(plr)
-- listen for Players to touch the block
local connection = baseFinal.Touched:Connect( function(hit)
if hit.Name == "Bloque" then
wait(0.6)
plr.stats.Money.Value = plr.stats.Money.Value + 5
hit:Destroy()
end
end)
-- hold onto the connection to clean it up later
connections[plr] = connection
end)
-- clean up when the Player leaves
game.Players.PlayerRemoving:Connect( function(plr)
connections[plr]:Disconnect()
end)
This is most likely because when you are trying to reference a value, you must put .Value after it in order to change the value itself. Assuming you have a stats folder, you should use plr.stats.Value.Value instead.
Next time, please show us your object structure so we have a better understanding of what the error is. Thanks.
I am trying to resolve wifi connectivity using Lua language. I have been combing through the api to find a solution but nothing solid yet. I asked a previous question, dynamically switch between wifi networks and the answer did address the question in the way I asked it, but it didn't accomplish what I expected.
Basically, I have two different networks from two different providers. All I want the ESP8266 12e to do is detect when or if the current network has no internet access and automatically switch to the next network. It must continuously try to connect at say a 3 minute interval until it is successful and not just give up.
For testing purposes I tried this code below. The plan is to use the variable "effectiveRouter" and write some logic to switch based on the current router.
effectiveRouter = nil
function wifiConnect(id,pw)
counter = 0
wifi.sta.config(id,pw)
tmr.alarm(1, 1000, tmr.ALARM_SEMI, function()
counter = counter + 1
if counter < 10 then
if wifi.sta.getip() == nil then
print("NO IP yet! Trying on "..id)
tmr.start(1)
else
print("Connected, IP is "..wifi.sta.getip())
end
end
end)
end
wifiConnect("myNetwork","myPassword")
print(effectiveRouter)
When I run that code, I get effectiveRouter as nil on the console. This tells me that the print statement ran before the method call was complete, print(effectiveRouter). I am very very new to lua as this is my first time with the language. I am certain this boiler plate code must have been done before. Can someone please point me in the right direction? I am open to shifting to the arduino IDE as I already have it set up for the NodeMCU ESP8266. May be I can follow the logic better as I come from a java-OOP background.
I eventually sat down and tested my sketch from the previous answer. Two additional lines and we're good to go...
What I missed is that wifi.sta.config() resets the connection attempts if auto connect == true (which is the default). So, if you call it to connect to AP X while it's in the process of connecting to X it will start from scratch - and thus usually not get an IP before it's called again.
effectiveRouter = nil
counter = 0
wifi.sta.config("dlink", "password1")
tmr.alarm(1, 1000, tmr.ALARM_SEMI, function()
counter = counter + 1
if counter < 30 then
if wifi.sta.getip() == nil then
print("NO IP yet! Keep trying to connect to dlink")
tmr.start(1) -- restart
else
print("Connected to dlink, IP is "..wifi.sta.getip())
effectiveRouter = "dlink"
--startProgram()
end
elseif counter == 30 then
wifi.sta.config("cisco", "password2")
-- there should also be tmr.start(1) in here as suggested in the comment
elseif counter < 60 then
if wifi.sta.getip() == nil then
print("NO IP yet! Keep trying to connect to cisco")
tmr.start(1) -- restart
else
print("Connected to cisco, IP is "..wifi.sta.getip())
effectiveRouter = "cisco"
--startProgram()
end
else
print("Out of options, giving up.")
end
end)
You better to migrate a callback based architecture to be sure that you have successfully connected. Here is doc for it :
https://nodemcu.readthedocs.io/en/master/en/modules/wifi/#wifistaeventmonreg
You can listen for
wifi.STA_GOTIP
And make your custom operations in it. Do not forget to start eventmon.
P.s. I am not able to see your variable effectiveRouter in related function.
I have a Lua script that sends an email to myself via SMTP. Everything works fine when uploading to the NodeMCU and saying dofile("sendemail.lua").
-- sendmail.lua
-- The email and password from the account you want to send emails from
MY_EMAIL = "REDACTED"
EMAIL_PASSWORD = "REDACTED"
-- The SMTP server and port of your email provider.
-- If you don't know it google [my email provider] SMTP settings
SMTP_SERVER = "isp.smtp.server"
SMTP_PORT = 25
-- The account you want to send email to
mail_to = "REDACTED"
-- Your access point's SSID and password
SSID = "REDACTED"
SSID_PASSWORD = "REDACTED"
-- configure ESP as a station
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,SSID_PASSWORD)
wifi.sta.autoconnect(1)
email_subject = ""
email_body = ""
count = 0
local smtp_socket = nil -- will be used as socket to email server
-- The display() function will be used to print the SMTP server's response
function display(sck,response)
print(response)
end
-- The do_next() function is used to send the SMTP commands to the SMTP server in the required sequence.
-- I was going to use socket callbacks but the code would not run callbacks after the first 3.
function do_next()
if(count == 0)then
count = count+1
IP_ADDRESS = wifi.sta.getip()
smtp_socket:send("HELO "..IP_ADDRESS.."\r\n")
elseif(count==1) then
count = count+1
smtp_socket:send("AUTH LOGIN\r\n")
elseif(count == 2) then
count = count + 1
smtp_socket:send("REDACTED".."\r\n")
elseif(count == 3) then
count = count + 1
smtp_socket:send("REDACTED".."\r\n")
elseif(count==4) then
count = count+1
smtp_socket:send("MAIL FROM:<" .. MY_EMAIL .. ">\r\n")
elseif(count==5) then
count = count+1
smtp_socket:send("RCPT TO:<" .. mail_to ..">\r\n")
elseif(count==6) then
count = count+1
smtp_socket:send("DATA\r\n")
elseif(count==7) then
count = count+1
local message = string.gsub(
"From: \"".. MY_EMAIL .."\"<"..MY_EMAIL..">\r\n" ..
"To: \"".. mail_to .. "\"<".. mail_to..">\r\n"..
"Subject: ".. email_subject .. "\r\n\r\n" ..
email_body,"\r\n.\r\n","")
smtp_socket:send(message.."\r\n.\r\n")
elseif(count==8) then
count = count+1
tmr.stop(0)
smtp_socket:send("QUIT\r\n")
print("msg sent")
else
smtp_socket:close()
end
print(count)
end
-- The connectted() function is executed when the SMTP socket is connected to the SMTP server.
-- This function will create a timer to call the do_next function which will send the SMTP commands
-- in sequence, one by one, every 5000 seconds.
-- You can change the time to be smaller if that works for you, I used 5000ms just because.
function connected(sck)
tmr.alarm(0,5000,1,do_next)
end
-- #name send_email
-- #description Will initiated a socket connection to the SMTP server and trigger the connected() function
-- #param subject The email's subject
-- #param body The email's body
function send_email(subject,body)
count = 0
email_subject = subject
email_body = body
smtp_socket = net.createConnection(net.TCP,0)
smtp_socket:on("connection",connected)
smtp_socket:on("receive",display)
smtp_socket:connect(SMTP_PORT, SMTP_SERVER)
end
-- Send an email
send_email("ESP8266", "[[Hi, How are your IoT projects coming along? Best Wishes,ESP8266]]")
However, I want to use a loop to monitor an analog input value and only send the email when certain analog input values are detected. Therefore, I added this code at the end of the script, after the sendemail() function definition and immediately before the function sendmail('subject', 'body') is called
vp = 0
gpio.mode(vp, gpio.INPUT)
while true do
local v = adc.read(vp)
if v < 840 or v > 870 then
print(v)
break
end
tmr.wdclr()
end
sendmail('subject', 'body')
The while loop works perfectly, waiting indefinitely for input from the analog pin. Once that input is found, it breaks correctly and calls the sendmail function. However, once that function is called, NodeMCU eventually resets. Sometimes it will get as far as successfully authenticating the SMTP credentials with the server, and sometimes it will not even make the HELO before it shuts down. What could possibly be causing this? Why would the sendmail.lua script work fine then suddenly decide not to work when adding this one small while loop that appears to work perfectly fine on its own?
A little quote from the NodeMCU reference:
tmr.wdclr() Feed the system watchdog.
In general, if you ever need to use this function, you are doing it
wrong.
The event-driven model of NodeMCU means that there is no need to be
sitting in hard loops waiting for things to occur. Rather, simply use
the callbacks to get notified when somethings happens. With this
approach, there should never be a need to manually feed the system
watchdog.
Please note the second line. :)
Not sure what your problem is, but why do you use a while loop in the first place? Why not use timer events to poll your ADC regularly?
Maybe the watchdog is triggered because your feed comes to late for some reason. In the if case you don't feed it at all befor you leave the loop.
Even if it may not be the definite answer I post it as such since the comment input is too small.
First, I suggest you use the script I posted for your previous question. This one isn't handling WiFi setup correctly. You need to wait in a timer until the device got an IP before you can continue. Remember, wifi.sta.config is non-blocking. And since it uses auto-connect=true if not set explicitly it'll try to connect to the AP immediately. That's also the reason why wifi.sta.autoconnect(1) is superfluous.
I don't understand the ADC reading code you posted.
vp = 0
gpio.mode(vp, gpio.INPUT)
Seems unnecessary to me because a) you don't do anything with GPIO 0 and b) adc.read only supports 0.
Rather than using a busy loop and constantly feeding the watch dog, which is a very bad sign, I suggest you use an interval based timer. Furthermore, I guess you don't wanna break the loop the first time the condition is met and never come back? So, you need to stay in the loop and keep triggering send mail, no? Something like this maybe (untested):
tmr.alarm(0, 200, tmr.ALARM_AUTO, function()
local v = adc.read(0)
if v < 840 or v > 870 then
node.task.post(function()
send_email("ESP8266", "[[Hi, How are your IoT projects coming along? Best Wishes,ESP8266]]")
end)
end
end)
I'm writting a lua script as wireshark(1.12.4) plugin to dissect my private protocols,I can get it work as normal dissector,which binding a certain port(such as 80) to DissectorTable "tcp.port".The pseudo-code as follows:
local my_pro = Proto("MyPro","My Protocol")
local my_pro_field_1 = ProtoField.uint16("MyPro.filed_1","Field 1",base.HEX)
local my_pro_field_2 = ProtoField.uint16("MyPro.filed_2","Field 2",base.HEX)
my_pro.fields = {my_pro_field_1,my_pro_field_2}
local data_dis = Dissector.get("data")
function my_pro.dissector(buf,pkt,root)
if (buf(0,2):uint() ~= 1 or buf(2,2):uint() ~= 1) then
data_dis:call(buf,pkt,root)
return false
end
pkt.cols.protocol = "My Protocol"
local tree = root:add(my_pro,buf(0,buf:len()))
tree:add_le(my_pro_field_1,buf(0,2))
tree:add_le(my_pro_field_2,buf(2,2))
return true
end
local tcp_encap_table = DissectorTable.get("tcp.port")
tcp_encap_table:add(80,my_pro)
The problem is:
What if My protocol is not running on a certain port,as I don't want to modify the port above every time,I actually want the dissector to be wise enough to dynamically identify some kind of pattern and do the right dissecting then.
I've searched out there's a so called "heuristic" dissector,I add codes below to test but I could't get it work.
local function my_heur_dissector(buf,pkt,root)
local ret = my_pro.dissector(buf,pkt,root)
if (not ret) then
return false
end
pkt.conversation = my_pro
return true
end
my_pro:register_heuristic("tcp",my_heur_dissector)
When I change the port,the packets're not parsed as my protocol,so I have to use "Decode as" menu.
So,how can I get the heuristic dissector work base on my code?Have I missed something?
BTW,the answer with code is appreciated.
Sadly, if you need a heuristic dissector (HD) it cannot be done in a plugin manner, and you need to write a new HD.
https://github.com/wireshark/wireshark/blob/master/doc/README.heuristic
(Yes, it has been over 2 years, but if some future-googler finds it...)
First of all, I'm new to Lua altogether, and this is my first attempt at writing a wireshark dissector.
My protocol is straightforward - a 2 byte length field, followed by a string of that length.
When I run the code through the Lua console, everything works as expected.
When the code is added to the Wireshark plugins directory, I get the error
Lua Error: [string "C:\Users...\AppData\Roaming\Wireshark..."]:15: calling 'add' on bad self (number expected, got string)
Line 15 corresponds is the t:add(f_text... line.
Can anyone explain the discrepancy between the execution methods?
do
local p_multi = Proto("aggregator","Aggregator");
local f_len = ProtoField.int16("aggregator.length","Length",base.DEC)
local f_text = ProtoField.string("aggregator.text","Text")
p_multi.fields = { f_len, f_text }
local data_dis = Dissector.get("data")
function p_multi.dissector(buf,pkt,root)
pkt.cols.protocol = "Aggregator"
local len = buf(0,2):int()
local t = root:add(p_multi,buf(0,len+2))
t:add(f_len,buf(0,2),"Length: " .. buf(0,2):int())
t:add(f_text,buf(2,len),"Text: " .. buf(2,len):string())
end
local tcp_encap_table = DissectorTable.get("tcp.port")
tcp_encap_table:add(4321,p_multi)
end
Your dissector code is very close to correct, but you're doing extra work that the interface won't accept. If you change your dissector function like so,
function p_multi.dissector(buf,pkt,root)
pkt.cols.protocol = "Aggregator"
local len = buf(0,2):int()
local t = root:add(p_multi,buf(0,len+2))
t:add(f_len,buf(0,2)) --let Wireshark do the hard work
t:add(f_text,buf(2,len)) --you've already defined their labels etc.
end
you'll get the desired behavior. The labels "Text" and "Length" are already defined for your fields, so there is no need to provide them again on lines 15 and 16.