ESP32 NodeMCU uart input matching strings problem - lua

I created a small project on ESP32 with nodemcu firmware which communicates with a sim808 module via uart2. My problem is, that the response from uart many times is not easy for interpretation within lua and nodemcu.
Here a short example of my code:
uart.on(2, "data", "\r", function(data)
print("Checking UART: "..data)
if (string.match(data, "RING")) then
print("Someone rings")
elseif (string.match(data, "CLIP:")) then
print("Phone number: "..data) -- shortened, I know that the whole line will appear
elseif (string.match(data, 'NO CARRIER')) then
print("Ring canceled")
else
print("Dont understand")
end
end, 0)
In above case - RING and NO CARRIER inputs are matching correctly and the proper info is given.
I have also many other such searchings which works. But when I look for the phone no (+CLIP:...) the code is ignorig this input, however I see it on the serial console output:
Checking UART:
Dont understand
Checking UART:
+CLIP: "+xxxxxxxxxxx",145,"",0,"",0
Checking UART:
Dont understand
I see also that this specific answer has new line character after and the loop goes again with no chars, maybe that's why the code can't find it, but the build in function uart.on should check every line (\r).
The same issue when I get some bluetooth command, also can't put it to a variable.

Related

Lua io.popen freezing after a while of reading a log file

I'm attempting to constantly read and parse a log file (Minecraft log file) by using io.popen in tandem with Ubuntu's tail command so that I can send some messages upon certain events.
Now, I have mostly everything working here, except one small issue. After a while of reading, the entire program just freezes.
Here is the relevant code:
-- Open the tail command, return a file handle for it.
local pop = io.popen(config.listen_command)
-- Simply read a single line, I've pulled this into its own
-- function so that if this ever needs changing I can do so
-- easily.
local function get_line()
logger:log(4, "READ LINE")
return pop:read("*l")
end
-- For each line in the log file, check if it matches any
-- of a list of patterns, return the matches and the
-- pattern information if so.
local function match_line()
local line = get_line()
logger:log(4, "Line: %s", line)
-- This all works, and I've tested that it's not freezing
-- here. I've just included it for completion of the call
-- -stack.
for event_type, data in pairs(config.message_patterns) do
for event_name, pattern in pairs(data) do
local matches = {line:match(pattern)}
if matches[1] then
return event_type, event_name, matches
end
end
end
end
-- The main loop, simply read a line and send a message
-- if there was a match.
logger:log(4, "Main loop begin.")
while true do
local event_type, event_name, matches = match_line()
-- ...
-- The rest of the code here is not relevant.
config.listen_command = "tail -F --lines=1 latest.log"
The issue is in the get_line function. After a while of reading the log file, it completely freezes on the pop:read("*l"). It prints the READ LINE message, but never prints the Line: <whatever data here> line.
This is a really strange issue that I've been getting really confused about. I've tried swapping to different distributions of Lua (Luvit, LuaJIT, Lua) and a very large amount of debugging, changing small things, rerunning, ... But I cannot think of anything that'd be causing this.
Perhaps there's something small I've missed.
So my question here is this: Why is pop:read("*l") freezing, even though more data is being outputted to the logfile? Is there a way to fix this? Perhaps to detect if the next read will freeze indefinitely, so I can try closing the popen'ed file and re-open it (or to preferably stop it happening altogether?)

I'm using ComputerCraft, a minecraft mod that adds computers, modems, and other peripherals. In this mod, you can write code using Lua

This is my first time using Lua, and with following a tutorial, Im making a chat program, allowing two players to send and receive messages to each other. The receiving is called chatreceive.lua. The script is:
rednet.open("right")
sender, message = rednet.receive()
print("computer " .. sender .. " has sent :")
print(message)
I keep getting an error saying
chatreceive.lua:3: attempt to concatenate global 'sender' (a nil value)
Any solutions? Ive been trying for a while now
That means that the variable 'sender' was nil. This probably means that there was some sort of error with rednet. You should add a lot of checks to make sure your programs don't fail in critical situations:
if sender==nil then
print("SENDER IS NIL!!!")
end
Also, what version of CC are you using? You shoud be more specific, to get better answers...

Capture ANSI escape sequence response using Micropython ESP8266

I'm using an ESP8266 with Micropython to communicate with a serial terminal using Putty. Using escape sequences like referenced in these questions:
Read ANSI escape from terminal
How do I determine size of ANSI terminal?
List of escape sequences https://vt100.net/docs/vt100-ug/chapter3.html
I am trying to read back an escape sequence that is a reply to find the cursor position.
I can see the response in the terminal, but I need to capture it so I can parse it. I'm familiar with Python, but a complete noob with Micropython and the ESP8266 (ESP01). I'm using the webrepl to upload the code. I saw this and I'm not sure if it's related: https://forum.micropython.org/viewtopic.php?t=5359
I've tried running my code without webrepl connected, but it still didn't work.
What am I doing wrong, how can I capture the response?
Depending on the terminal size, the response should be something like below, the stuff before the ; will not be visible.
^[[45;157R
#import esp
import network
import machine
from machine import UART
uart = UART(0, 115200)
x=uart.write("\033[500;500H\033[6n")
if uart.any():
print(":> ", uart.read())
EDIT: Tried example from this link https://forum.micropython.org/viewtopic.php?t=5359#p30867
No luck with that either (yes, I know it's blocking). Here if I type the letter 'R', it drops out of the loop, but it's not catching the output from the escape sequence.
from machine import UART
import machine
import network
import uos
uos.dupterm(None, 1)
uart = UART(0, 115200)
charbuf = None
uart.write("\033[500;500H\033[6n")
while charbuf != b"R":
if uart.any():
charbuf = uart.read()
uart.write(charbuf)
uos.dupterm(UART(0, 115200), 1)
Solving this was a nightmare, the WebRepl console replication has been the bane of my existence and probably many others. I tried multiple read() methods and they all failed.
uart.read()
sys.stdin.read()
sys.stdin.buffer.read()
Those were in combination of enabling/disabling the console duplication for webrepl.
The incantation that finally worked for me is below. See inline comments for more details.
import machine
import network
#import sys
import uos
from machine import UART
uos.dupterm(None, 1) # Disable console duplication for Webrepl
uart = UART(0, 115200, timeout=100, timeout_char=100) #Instantiate uart, increase timeout for good measure
uart.write("\033[2J\033[1;1f") # Clear screen
uart.write("\033[500;500H\033[6n") # Move cursor to bottom right, send query.
# Wait for uart to collect response. This will block further execution until we get a reply.
while True:
if uart.any() != 0:
break
uos.dupterm(UART(0, 115200), 1) # Re-enable console redirection so print() will work
# Read the uart buffer with response, convert from binary to string, replace ESC character.
# First ^ gets eaten somewhere!
buf = str(uart.read(), 'UTF-8').replace('\x1b', '^^[')
if len(buf) > 0: # If response isn't empty, print buffer
print(buf)
This is the Output:
^[[43;157R

Lua script pc to sleep

So i got a new keyboard wit hG-keys. (hotkeys) And i'm not familiar with lua...
So could anybody give me a very simple command that sets my pc to sleep? please?
if gkey == 7 and mkey == 1 then
if event == "G_PRESSED" then
end
end
gkeys
so gkey is the key that is pressed, and mkey is the set it uses. i can have up to 54 differint scripts/macro's.
I want to know what i have to put after the last 'then' so my pc goes to sleep.
thx ahead
edit 1:
got this:
if gkey == 1 and mkey == 3 then
if event == "G_PRESSED" then
execute("rundll32.exe powrprof.dll,SetSuspendState 0,1,0");
end
end
error is: [string "LuaVM"]:40: attempt to call global 'execute'(a nil value)
and with os.execute i get this error:
[string "LuaVM"]:40: attempt to index global 'os'(a nil value)
final answer: not possible with gseries keyboard. use a shortcut
Given the reference to G-keys and the G_PRESSED in your code snippet, I am assuming you have one of the Logitech G-Series keyboards. These keyboards can be programmed so that certain keys run Lua scripts using a custom Lua 5.1 interpreter. The documentation is included with Logitech's Gaming Software program.
According to the documentation, only some of the standard library functions are supported: the string, math and table are available. However, the io, os and debug libraries are not available.
So I doubt you'll be able to make your PC go to sleep.
EDIT in response to OP edit: the Lua library you have access to has the os library removed, so you're probably not going to be able to make your computer sleep directly.
There might be an indirect way to do this by writing something that listens for debugging messages, which you can generate with OutputDebugMessage. There's a Team Speak plugin that does this. But it's probably beyond your programming ability right now and far beyond the scope of a Stackoverflow post to explain.
You can use os.execute to run an executable from Lua.
If you google "Windows sleep command line" you'll get another Stackoverflow post which shows two ways of doing it. One requires that you turn hibernation off, the other requires that you download an additional utility (PsShutdown).
Assuming you've downloaded PsShutdown and put it somewhere in your PATH, then you can use the following to sleep the computer:
os.execute('psshutdown -d -t 0')

Lua - io.read sends me an echo back when I read from serial port - why?

I am writing a code in Lua to read from a serial port, but when I read I receive an echo back with the code :
print("Dragino Uart Test started\n")
while 1 do
serialin=io.open("/dev/ttyS0","r")
print(serialin:read()) --print the data
serialin:close()
end
When I open minicom to send him some data, I enable local echo than I type "text" and I see :
tteexxtt
Then I need to press enter to see my message in my lua script.
I am using a OpenWRT in a Dragino.
It seems that it is like a prompt command that you type every thing that you see and you need to press enter to send you command.
There is any other way to read and write to/from a serial port?
Can somebody help me please? Thank you so much!
The read method with no arguments reads a full line. That's why you need to press enter at the end of the text. Try reading one byte at a time with :read(1) or all of it with :read("*a").
I don know if this is still an issue to someone but maybe this helps a few people. Like lhf said :read(1) is a gread way of doing this. I had a few problems with :read("*a") though. In my opinion the easiest way of doing this is to append the answer piece by piece like:
rserial=io.open("/dev/ttyS0",'r')
lines = ""
repeat
local line=rserial:read(1)
if string.sub(line, 0, 3) == "OED" then --OED is here the stream ending. This can vary
EOD = true
rserial:close()
elseif line then
lines = lines .. line
end
until EOD == true
print (lines)

Resources