TCP connection crashes after reading only a few strings - sockets

I'm working with the ESP8266 wifi module programming it in LUA using NodeMCU. I was able to connect from an iPhone app to the TCP server created by the wifi module to send 3 floats. I parse the huge string into 3 strings and send them using uart to and Arduino. It works just fine but after about 10 inputs it crashes/freezes. I need the constant flow of data to keep coming but consistently and I'm unable to do it reliably.
I've printed after each line to keep track of what is actually happening and even after that i'm still not sure what is going on.
Code
`
print("11\n")
wifi.setmode(wifi.STATION)
print("22\n")
wifi.sta.config("WDTS03","Walker14!")
print("33\n")
elWiFi =(wifi.sta.getip())
if elWiFi ~= nil then
print(wifi.sta.getip())
end
print("44\n")
if srv~=nil then
print("444\n")
srv:close()
print("555 \n")
end
print("Create server \n")
srv=net.createServer(net.TCP)
print("1\n")
if srv ~= nil then
print("srv !=nil \n")
srv:listen(6969,function(conn)
print("listening \n")
if conn ~= nil then
print("incoming\n")
conn:on("receive",function(conn,numbers)
print("2\n")
print(#numbers)
print("chekcing for nil \n")
if numbers ~= nil then
print("3\n")
p = string.find(numbers, "x=")
print("4\n")
q = string.find(numbers, "&y")
print("5\n")
if p ~= nill then
print("6\n")
if q ~= nil then
print("7\n")
x = (string.sub(numbers,p+2, q-1))
print("x=" .. x)
end
end --p ~= nill
print("8\n")
p = string.find(numbers, "y=")
print("9\n")
q = string.find(numbers, "&z")
print("10\n")
if p ~= nill then
print("11\n")
if q ~= nil then
print("12\n")
y = (string.sub(numbers,p+2, q-1))
print("y=" .. y)
end
end --p ~= nill
print("13\n")
p = string.find(numbers, "z=")
print("14\n")
q = string.find(numbers, " H")
print("15\n")
if p ~= nill then
print("16\n")
if q ~= nil then
print("17\n")
z = (string.sub(numbers,p+2, q-1))
print("z=" .. z)
end
end-- p ~= nill
print("18\n")
end --numbers ~= nil
print("54\n")
--conn:send("test\n")
end)
print("55 \n")
end
print("66 \n")
end)
print("77\n")
end
print("666\n")`
and I get the following output
11
22
33
44
Create server
1
srv !=nil
77
666
> listening
incoming
55
66
listening
incoming
55
66
listening
incoming
55
66
listening
incoming
55
66
2
338
chekcing for nil
3
4
5
6
7
x=0.1722259521484375
8
9
10
11
12
y=-0.7733306884765625
13
14
15
16
17
z=-0.5716094970703125
18
54
2
337
chekcing for nil
3
4
5
6
7
.
.--repeats a few times
.
y=-0.005340576171875
13
14
15
16
17
z=-0.9838409423828125
18
54
PANIC: unprotected error in call to Lua API (attempt to call a nil value)
�l� �=+���T2n���
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
11
22`
It fails on the "conn:on" argument for "srv:listen" after a few times
Thanks for the help and sorry if formatting is messed up. First time

Too long for a comment, sorry.
PANIC: unprotected error in call to Lua API (attempt to call a nil value)
Hard to tell which value was nil/null. Create a Minimal, Complete, and Verifiable Example (MCVE) to reduce the amount of code one needs to analyze.
The following snippet will eventually lead to out-of-memory due to closed upvalues. Each of your callback functions should use its own copy of the passed socket instance rather referencing the one of a wrapping callback function. The third line should NOT re-use the conn variable but define one with a new name.
See https://stackoverflow.com/a/37379426/131929 for details.
srv:listen(6969,function(conn)
if conn ~= nil then
conn:on("receive",function(conn,numbers)
NodeMCU 0.9.6 build 20150704
Don't use those old 0.9.x binaries, they're outdated and contain lots of bugs. http://nodemcu.readthedocs.io/en/latest/en/#getting-started helps you get started with a new firmware.

Related

CLLE SNDRCVF command not allowed

I am trying to compile this piece of CL code using Rational Series but keep getting error.
This is my CL code:
PGM
DCLF FILE(LAB4DF)
SNDRCVF RCDFMT(RECORD1) /* send, recieve file */
DOWHILE (&IN03 = '0')
SELECT
WHEN (&USERINPUT = '1' *OR &USERINPUT = '01') CALLSUBR OPTION1
OTHERWISE DO
*IN03 = '1'
ENDDO
ENDSELECT
ENDDO
SUBR OPTION1
DSPLIBL
ENDSUBR
ENDPGM
And this is my DSPF code
A R RECORD1
A 1 38'LAB 4'
A 3 3'Please select one of the following-
A options:'
A 6 11'3. Maximum Invalid Signon Attempt-
A s allowed'
A 8 11'5. Run Instructor''s Insurance Pr-
A ogram'
A 5 11'2. Signed on User''s Message Queu-
A e'
A 1 3'Yathavan Parameshwaran'
A 7 11'4. Initial number of active jobs -
A for storage allocation'
A 4 11'1. Previous sign on by signed on -
A user'
A 14 11'F3 = Exit'
A 14 31'F21 = Command Line'
A 2 70TIME
A 1 72DATE
A 9 11'Option: '
A USERINPUT 2 B 9 19
A 91 DSPATR(RI)
A 92 DSPATR(PC)
A MSGTXT1 70 O 11 11
A MSGTXT2 70 O 12 11
Is there a problem with my CL code or DSPF code?
You forgot to say what error you were getting. It's always important to put all the information about error messages into your questions.
There are two errors.
&IN03 is not defined
Your assignment to *IN03 should be to &IN03, but that's not how you do an assignment in CLP
If you want to be able to press F3, you have to code something like CA03(03) in the "Functions" for the record format.
To assign a variable in CL, code
CHGVAR name value
Looking at the documentation here, I suspect you need to add RCDFMT to your DCLF spec like so:
DCLF FILE(LAB4DF) RCDFMT(RECORD1)
SNDRCVF RCDFMT(RECORD1) /* send, recieve file */
If you really do only have 1 record format in your display file, then you can also omit the RCDFMT from both commands like so:
DCLF FILE(LAB4DF)
SNDRCVF /* send, recieve file */

reading specific lines from .txt file

I have large text file which has lots of information inside. I need to access only a line which stars with '***'. That line contains 17 numbers with a space between them.
Example of the file is,
Msg count = 2629
max send msg count = 34
avg send msg count = 10.27
imbalance send msg count = 3.31
------------------------------
max recv msg count = 35
avg recv msg count = 10.27
imbalance recv msg count = 3.41
***1.100020 306852 1381937 11045 5398.19 2.05 10465 5398.19 1.94 2629 34 10.27 3.31 35 10.27 3.41 0.000000
[INFO] +++ Sat Sep 24 15:15:33 2016
+++ (test.c:816) stat1 end
Is there a way to do this?
Try to use this code:
infilename = 'nameoffile.txt'; % name of your file
m = memmapfile(infilename); % load file to memory (and after close it)
instrings = strsplit(char(m.Data.'),'\n','CollapseDelimiters',true).';
checkstr = '***';
% find all string (their indices) starting with checkstr
ind = find(strncmpi(instrings,checkstr,length(checkstr)));
if isempty(ind)
fprintf('\n No strings with %s',checkstr)
else
% first string with string checkstr
instrings(ind(1));
end

Reading data only when present

I'm trying to read the data from the COM3 port.
I'm using this code:
in = fscanf(s);
if(in == 'A')
fclose(s);
break;
end
The problem is that when no data is sent to the com3 port, the fscanf() will wait for a certain time interval and then give a timeout.
Is there a way to read data only when it is present?
Read only when data present
You can read out the BytesAvailable-property of the serial object s to know how many bytes are in the buffer ready to be read:
bytes = get(s,'BytesAvailable'); % using getter-function
bytes = s.BytesAvailable; % using object-oriented-addressing
Then you can check the value of bytes to match your criteria. Assuming a char is 1 byte, then you can check for this easily before reading the buffer.
if (bytes >= 1)
in = fscanf(s);
% do the handling of 'in' here
end
Minimize the time to wait
You can manually set the Timeout-property of the serial object s to a lower value to continue execution earlier as the default timeout.
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
Most likely you will get the following warning:
Unsuccessful read: A timeout occurred before the Terminator was
reached..
It can be suppressed by executing the following command before fscanf.
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
Here is an example:
s = serial('COM3');
set(s,'Timeout',1); % sets timeout to 1 second (default is 10 seconds)
fopen(s);
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
in = fscanf(s);
warning('on','MATLAB:serial:fscanf:unsuccessfulRead');
if(in == 'A')
fclose(s);
break;
end

How can a circle touch a line in Qbasic and end the program?

I am trying to make a maze in Qbasic but when the pointer touches the maze lines then the program is not ending. I want that when the circle (which is the pointer ) touches the ends of the maze then the program should go to an end.The Program is this:-
cls
screen 12
DIM p AS STRING
DIM A1 AS STRING
15 print"What do you want to do?"
print"A:Draw AN IMAGE"," B:PLAY A MAZE GAME";
PRINT
PRINT"TYPE 'A' OR 'B'IN CAPITAL FORM"
GOTO 102
99 print "rules to play the maze game:"
print
print "1 use 'W' to move the ball foward"
print "2 use 'S' to move the ball backward"
print "3 use 'A' to move the ball leftward"
print "4 use 'D' to move the ball rightward"
INPUT A1
CLS
goto 10
102 INPUT P
if p="A"then
cls
goto 20
elseif p="B" then
cls
goto 99
elseif p<>"A" AND p<>"B" then
print "Choose between A and B"
GOTO 70
end if
10 pset(120,120)
draw "r100"
pset (120,140)
draw"r80"
pset (200,140)
draw "d100"
pset (220,120)
draw"d140"
pset (220,260)
draw "l90"
pset (200,240)
draw "l50"
pset (130,260)
draw"u50l120u90r60u40l50u60r300d90l35d260l60d30l80
h20l20h20u30r40u5l70d60f40r250u90h40u45r40u40r50u130h40r225d65l50d60l15
d130l40d50l20d15r45d40r20u45r10u10r10u90r100"
pset(150,240)
draw"u50l120u50r60u80l50u20r260d50l35d260l60d30l40h20l20h10r
40u50l120d98f50r290u115h40u20r40u40r50u160h10r140d20l50d60l15
d130h40d90l20d60r45d45r70u45r10u10r10u90r75"
20 dim k as string
x = 110
y = 105
do
k = ucase$(inkey$)
if k="W"then
y = y - 2
elseif k= "S" then
y = y + 8
elseif k="A"then
x = x - 8
elseif k="D" then
x = x + 5
end if
circle (x,y),7,10
loop until k ="Q"
GOTO 45
70 CLS
GOTO 15
if x=120 and y=120 then goto 45
40 cls
45 END
Pls Help
Thanks in Advance....
Ok, let's take a peak at your game loop presented below and reformated a bit for readability:
do
k = ucase$(inkey$)
if k="W"then
y = y - 2
elseif k= "S" then
y = y + 8
elseif k="A"then
x = x - 8
elseif k="D" then
x = x + 5
end if
circle (x,y),7,10
loop until k ="Q"
Your win case (if x=120 and y=120 then goto 45) doesn't actually occur within the loop but outside it.
With do loops, only the code between the do and loop statement will execute unless the "until" statement returns true. In order words:
do
'This code will execute
loop until k = "Q"
'This code will only execute after k=Q
Put the win case in the do loop and it should work.
If I recall correctly, QBasic allows whitespace in the beginning of a line. I recommend using whitespace to organize your code visually so you can see what's going on. Look at how I formatted your main loop. Everything that the do loop controls is tabbed to the right of the do and loop statement. This way you can easily see what the do loop is doing. Everything in the if statement gets the same treatment for similar reasons.
If you get in the habit of indenting your code, you can start to see the code's logic laid out cleanly.
Edit: It seems you're new to programming. If you enjoy it, I recommend learning Python through codecademy rather than QBasic. QBasic encourages some very bad habits, like goto statements.

How to calculate a Mod b in Casio fx-991ES calculator

Does anyone know how to calculate a Mod b in Casio fx-991ES Calculator. Thanks
This calculator does not have any modulo function. However there is quite simple way how to compute modulo using display mode ab/c (instead of traditional d/c).
How to switch display mode to ab/c:
Go to settings (Shift + Mode).
Press arrow down (to view more settings).
Select ab/c (number 1).
Now do your calculation (in comp mode), like 50 / 3 and you will see 16 2/3, thus, mod is 2. Or try 54 / 7 which is 7 5/7 (mod is 5).
If you don't see any fraction then the mod is 0 like 50 / 5 = 10 (mod is 0).
The remainder fraction is shown in reduced form, so 60 / 8 will result in 7 1/2. Remainder is 1/2 which is 4/8 so mod is 4.
EDIT:
As #lawal correctly pointed out, this method is a little bit tricky for negative numbers because the sign of the result would be negative.
For example -121 / 26 = -4 17/26, thus, mod is -17 which is +9 in mod 26. Alternatively you can add the modulo base to the computation for negative numbers: -121 / 26 + 26 = 21 9/26 (mod is 9).
EDIT2: As #simpatico pointed out, this method will not work for numbers that are out of calculator's precision. If you want to compute say 200^5 mod 391 then some tricks from algebra are needed. For example, using rule
(A * B) mod C = ((A mod C) * B) mod C we can write:
200^5 mod 391 = (200^3 * 200^2) mod 391 = ((200^3 mod 391) * 200^2) mod 391 = 98
As far as I know, that calculator does not offer mod functions.
You can however computer it by hand in a fairly straightforward manner.
Ex.
(1)50 mod 3
(2)50/3 = 16.66666667
(3)16.66666667 - 16 = 0.66666667
(4)0.66666667 * 3 = 2
Therefore 50 mod 3 = 2
Things to Note:
On line 3, we got the "minus 16" by looking at the result from line (2) and ignoring everything after the decimal. The 3 in line (4) is the same 3 from line (1).
Hope that Helped.
Edit
As a result of some trials you may get x.99991 which you will then round up to the number x+1.
You need 10 ÷R 3 = 1
This will display both the reminder and the quoitent
÷R
There is a switch a^b/c
If you want to calculate
491 mod 12
then enter 491 press a^b/c then enter 12. Then you will get 40, 11, 12. Here the middle one will be the answer that is 11.
Similarly if you want to calculate 41 mod 12 then find 41 a^b/c 12. You will get 3, 5, 12 and the answer is 5 (the middle one). The mod is always the middle value.
You can calculate A mod B (for positive numbers) using this:
Pol( -Rec( 1/2πr , 2πr × A/B ) , Y ) ( πr - Y ) B
Then press [CALC], and enter your values for A and B, and any value for Y.
/ indicates using the fraction key, and r means radians ( [SHIFT] [Ans] [2] )
type normal division first and then type shift + S->d
Here's how I usually do it. For example, to calculate 1717 mod 2:
Take 1717 / 2. The answer is 858.5
Now take 858 and multiply it by the mod (2) to get 1716
Finally, subtract the original number (1717) minus the number you got from the previous step (1716) -- 1717-1716=1.
So 1717 mod 2 is 1.
To sum this up all you have to do is multiply the numbers before the decimal point with the mod then subtract it from the original number.
Note: Math error means a mod m = 0
It all falls back to the definition of modulus: It is the remainder, for example, 7 mod 3 = 1.
This because 7 = 3(2) + 1, in which 1 is the remainder.
To do this process on a simple calculator do the following:
Take the dividend (7) and divide by the divisor (3), note the answer and discard all the decimals -> example 7/3 = 2.3333333, only worry about the 2. Now multiply this number by the divisor (3) and subtract the resulting number from the original dividend.
so 2*3 = 6, and 7 - 6 = 1, thus 1 is 7mod3
Calculate x/y (your actual numbers here), and press a b/c key, which is 3rd one below Shift key.
Simply just divide the numbers, it gives yuh the decimal format and even the numerical format. using S<->D
For example: 11/3 gives you 3.666667 and 3 2/3 (Swap using S<->D).
Here the '2' from 2/3 is your mod value.
Similarly 18/6 gives you 14.833333 and 14 5/6 (Swap using S<->D).
Here the '5' from 5/6 is your mod value.