lua: init.lua:15: attempt to call method 'alarm' (a nil value) - lua

i am trying to fix a piece of code i did find online. (yeah i know....)
But in case you guys can help me out wihth this error it would be just amazing:
Error: lua: init.lua:15: attempt to call method 'alarm' (a nil value)
Code (from here: https://github.com/Christoph-D/esp8266-wakelight)
dofile("globals.lc")
wifi.setmode(wifi.STATION)
wifi.sta.config(WIFI_SSID, WIFI_PASSWORD)
wifi.sta.sethostname(MY_HOSTNAME)
if WIFI_STATIC_IP then
wifi.sta.setip({ip = WIFI_STATIC_IP, netmask = WIFI_NETMASK, gateway = WIFI_GATEWAY})
end
wifi.sta.connect()
-- Initialize the LED_PIN to the reset state.
gpio.mode(LED_PIN, gpio.OUTPUT)
gpio.write(LED_PIN, gpio.LOW)
tmr.alarm(
MAIN_TIMER_ID, 2000, tmr.ALARM_AUTO, function ()
if wifi.sta.getip() then
tmr.unregister(MAIN_TIMER_ID)
print("Config done, IP is " .. wifi.sta.getip())
dofile("ledserver.lc")
end
end)
What can i do there? Whats wrong?
Cheers and thank you!!!

It is all in the manual. You just have to read it.
There is an example of how to use the alarm method of timer objects.
if not tmr.create():alarm(5000, tmr.ALARM_SINGLE, function()
print("hey there")
end)
then
print("whoopsie")
end
You attempted to call tmr.alarm but it is tobj:alarm. The manual does not mention tmr.alarm. This function was removed from NodeMCU in January 2019.
You're using code you found online that is basedn on an older NodeMCU version. It is using functions that are deprecated by now.
See https://github.com/nodemcu/nodemcu-firmware/pull/2603#issuecomment-453235401
and
https://github.com/nodemcu/nodemcu-firmware/compare/5b22e1f9aee77095ab99dd6240ebd9dddd1cc5a0..c6444ecb6088d20e95197d808d8303c8093faab5
So you have to create a timer object first befvor you can use any of its methods. alarm is not a method of the tmr module anymore.
Edit
First you have to create a timer object https://nodemcu.readthedocs.io/en/latest/modules/tmr/#tobjcreate
local tObj = tmr.create()
Then you have to register a callback and start the timer. There is a convenience function alarm that does both for us.
And when we do not need our timer anymore we have to free the resources by calling
tObj:unregister()
Try something like
-- create a timer object
local tObj = tmr.create()
-- register an alarm
tObj:alarm(2000, tmr.ALARM_AUTO, function ()
if wifi.sta.getip() then
tObj:unregister()
print("Config done, IP is " .. wifi.sta.getip())
dofile("ledserver.lc")
end
end)

Related

What does "attempt to index function with 'Connect'" mean in Roblox?

local Player = game.Players.LocalPlayer
local PlayerCash = Player:WaitForChild("leaderstats"):WaitForChild("Strength")
local Mouse = Player:GetMouse()
local amount = 50
script.Parent.Activate:Connect(function()
game.Players.LocalPlayer.leaderstats.money.Value = game.Players.LocalPlayer.leaderstats.money.Value + amount
end)
I am trying to make a code to give Strength when you click. When I press 'Play' it doesn't work. All it says in the output is
'attempt to index function with 'Connect'.'
The error "attempt to index [type] with [field name]" means that you are incorrectly using something like an object, and you are trying to access some field on it.
In your case, this error is pointing at the line : script.Parent.Activate:Connect.This says that script.Parent.Activate is a function and not a table, and you cannot call Connect on a function. This is just to help us figure out what is wrong with our code.
Since you working with Tools, there is a simple fix. Instead of using the Activate function, you are looking for the Activated event. So just change update that line like this :
script.Parent.Activated:Connect(function()
It connects a function to an event that happened, like this:
local tool = script.Parent
-- It connects the event (the tool being equipped) to a function.
tool.Equipped:Connect(function()
-- CODE
end)
Also, the answer above is how you can fix your problem and here's a shortcut: You have defined "Player" and you could've used it inside the function. Have a great day and God bless everyone here.

Why do I use 'end)' instead of just end |?

draw.RoundedBox(0,0,0,100,100,Color(120,255,120))
end)
I'm watching tutorials for learning Lua, more specifically Lua for the Garry's Mod engine. During the tutorial, I noticed using just 'end' didn't work. I had to use 'end)' with a ')'.
Why do I have to place a ')' at the end of end in this code?
Some functions take other functions as parameters.
When you see a function called like this:
hello(param, function(a) print(a) end)
(Sorry, poor example. This function doesn't really do anything) The function on the inside is called internally from the source of the hello function.
The end is the end of the inside function, and the ) is the end of the parameter list for the first function.
So here we have a function hook.Add() being called:
hook.Add("HUDPaint", "DrawMyHud", function()
draw.RoundedBox(0,0,0,100,100,Color(120,255,120))
end)
and from the GMOD wiki:
hook.Add( string eventName, any identifier, function func )
--Add a hook to be called upon the given event occurring.
Although we're calling a function, what the function is doing is creating a special connection in the code called a hook. On the event "HUDPaint", the GMOD client will call the function provided.
Another way to write this function that might make the meaning of end) more clear is by making each parameter it's own line:
hook.Add(
"HUDPaint",
"DrawMyHud",
function() draw.RoundedBox(0,0,0,100,100,Color(120,255,120)) end --end of function declaration
) --end of hook.Add function call

PANIC: unprotected error in call to Lua API (init.lua:116: attempt to call field 'alarm' (a nil value))

I keep getting an error on this line of code, how can I solve this? Thanks in advance
tmr.alarm(0, 250, tmr.ALARM_AUTO, function()
You are obviously using an outdated example snippet from somewhere. There is no tmr.alarm function in the timer module.
See https://nodemcu.readthedocs.io/en/latest/modules/tmr/ for the current API documentation. There is a alarm() function on a timer object i.e. you first need to create a timer object. The below example is straight from the documentation:
if not tmr.create():alarm(5000, tmr.ALARM_SINGLE, function()
print("hey there")
end)
then
print("whoopsie")
end

nodemcu with Lua and 8266 tmr.stop

Note: This is a copy of a question asked here
Hi
I am completely new to EPS8266 and Lua (but not to programming - my first CPU was an 8080...)
Using a nodemcu HUZZA from adafruit
Anyway I am testing some timer stuff and running into this:
tmr.alarm(0, 500, 1, function()
print("I'm here")
tmr.stop(0)
end)
Without the stop, the loop keeps printing, with it the tmr.stop(0) stops. ... so far so good.
But if I want to start the timer again like:
tmr.alarm(0, 500, 1, function()
print("I'm here")
tmr.stop(0)
-- do some stuff
tmr.start(0)
end)
I get an error: PANIC: unprotected error in call to Lua API...
The documentation says that the tmr is still registered when stop is called.
A call to tmr.state(0) does the same. Only tmr.stop(0) seems to works as expected.
Thanks for your thoughts.
The documentation says to no longer use static timers
Static timers are deprecated and will be removed later. Use the OO API initiated with tmr.create().
If you want complete control over when the functions in the timer callback are executed you need a ALARM_SEMI instance upon which you call start whenever needed. It'll fire exactly once for every time you call start on it.
local mytimer = tmr.create()
mytimer:register(500, tmr.ALARM_SEMI, function() print("I'm here") end)
-- do stuff here
-- then whenever needed trigger the timer
mytimer:start()
Note that mytimer is not unregistered and not garbage collected.
Based on the documentation, you need to use tmr.ALARM_SEMI as your alarm mode.
ALARM_SEMI is described by the documentation as:
tmr.ALARM_SEMI manually repeating alarm (call tmr.start() to
restart)
tmr.ALARM_SEMI is equal to 2. Based on that, this should work:
tmr.alarm(0, 500, 2, function()
print("I'm here")
tmr.stop(0)
-- do some stuff
tmr.start(0)
end)

Attempt to index global 'websocket'

I'm pretty new to the ESP8266. I'm trying to add the WebSockets to the Lua code, but everytime I try to use the WebSocket looking at the documentation, the device throws error as attempt to index global websocket (a nil value). I'm not really sure if there is something to be imported, can anyone please help me with this.
function connectToSocket()
print ("Connect to socket called, OK.")
local ws_client = websocket.createClient()
end
wifi.setphymode(wifi.PHYMODE_N)
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","PWD")
wifi.sta.eventMonReg(wifi.STA_IDLE, function() print("IDLE") end)
wifi.sta.eventMonReg(wifi.STA_CONNECTING, function() print("CONNECTING...") end)
wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() print("WRONG PASSWORD!!!") end)
wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() print("NO SUCH SSID FOUND") end)
wifi.sta.eventMonReg(wifi.STA_FAIL, function() print("FAILED TO CONNECT") end)
wifi.sta.eventMonReg(wifi.STA_GOTIP, function()
print("GOT IP "..wifi.sta.getip())
connectToSocket()
end)
wifi.sta.eventMonStart()
wifi.sta.connect()
I see three problems with the above code.
The main issue appears to be that your firmware is missing the websocket module. Uncomment https://github.com/nodemcu/nodemcu-firmware/blob/master/app/include/user_modules.h#L75 if you happen to build it manually.
Furthermore, all event handlers need to be registered before the respective events have a chance to be fired. I see you intend to do exactly that. However, by default wifi.sta.config uses auto connect=true in which case the WiFi registration process starts before the event monitor is started.
Lastly, the signature for wifi.sta.config changed a few months ago (see docs for details). Now you'd have to say wifi.sta.config{"SSID","PWD"} thereby passing a Lua table.

Resources