As the title says... Chat on...

User avatar
By cdrwolfe
#7478 Hi,

I was wondering if it is possible to use the ESP8266 as and AP, have multiple clients (laptops) connect to this AP, i.e 192.168.4.2 and 192.168.4.3, and have the AP send messages to the two clients, outside of the conn:on recieve callback.

What I have tried below is basically setting up the AP, creating a server and listening for any connections from the clients, i.e 192.168.4.2. The client sends a simple message '0' which the script can interpret to call a specific function. This function can then perform some task and if necessary (and it is) connect to the client and send a message back.

I relatively new to this area and sockets, servers and clients, and where I can successfully call the function DoSomething, and the callback returns 'Recieved' to my python script, i don't recieve the send for 'Step 1'. Maybe I'm doing the impossible, communicating through the same port at the same time when I shouldn't be? I'm not sure so any help is appreciated.

Code: Select all-- Configure access point
wifi.setmode(wifi.STATIONAP)
-- Declare configuration variable
cfg={}
cfg.ssid="SSID"
cfg.pwd="password"
-- Pass to access point and configure
wifi.ap.config(cfg)
-- Get current internal state
-- Load internal server to handle all communications
-- Check if server is available or create
if srv == nil then
-- Create server
srv=net.createServer(net.TCP)
-- a simple http server
srv:listen(80,function(conn)
    conn:on("receive",function(conn,payload)
    -- Print payload message
    print(payload)
    -- Call task function and pass payload
    local output = Task(payload)
    -- Send back any response to caller or all clients
    conn:send(output)
    end)
end)
end

-- Depending on payload call certain functions
function Task (command)
     -- Declare variable to hold output
     local output = ""
     -- Select task
     if command == "0" then
          -- Do something '0'
          output = DoSomething()
     end
     -- Return output
     return output
end

function DoSomething ()
     -- Command clients to do something
     print("Step 1")
     sck = net.createConnection(net.TCP, false)
     sck:connect(80,"192.168.4.2")
     sck:send("Step 1")
     -- Sleep
     tmr.delay(1000)
     -- Return result
     return 'Recieved'
end
User avatar
By ThomasW
#7500 I don't know if this solves all your problems but I think 'DoSomething' should look like this (not tested, just typed):
Code: Select allfunction DoSomething ()
     -- Command clients to do something
     print("Step 1")
     local sck = net.createConnection(net.TCP, false)
     sck:on("sent",function(sck)
          sck:close() 
     end)
     sck:on("connection",function(sck)
          sck:send("Step 1")
     end)
     sck:connect(80,"192.168.4.2")
     -- Return result
     return 'Recieved'
end

...to make sure you don't invoke send() before the connection is even made and to close the connection correctly. Also note 'local sck...' - in lua all variables are global by default (and you don't want a global accessible socket here). No need for a delay also - all is happening in the callbacks and tmr.delay() blocks networking anyways. BTW - if you plan to expect a result from the send() in 'DoSomething' you'll have of course to add a on:"receive" event and things will get more complicated as you can't really wait for the answer,,,

HTH
Thomas
User avatar
By cdrwolfe
#7518 Thanks Thomas,

I implemented your changes and so far it all seems to be working, I had to add a time delay in my python script because closing the connection 'conn.close()' apparently hangs about a bit even if you call it so in my test loop it would never call another function. But all seems to be working now.

Code: Select all#! /usr/bin/env python
import socket
import sys
import time

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = ('192.168.4.1', 80)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)
# Create a TCP/IP socket
sockLocal = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind to local IP and port
sockLocal.bind(('192.168.4.2', 80))
# Set socket to listen
sockLocal.listen(10)


def Function1():
       # Send data
       message = '0'
       print >>sys.stderr, 'sending function 1 message "%s"' % message
       sock.sendall(message)
       data = sock.recv(160)
       print >>sys.stderr, 'Server Data Function 1 "%s"' % data
   # Receiving from client
   # wait to accept a connection - blocking call
   conn, addr = sockLocal.accept()
   print 'Connected with ' + addr[0] + ':' + str(addr[1])
        dataLocal = conn.recv(1024)   
   print >>sys.stderr, 'Socket Data Function 1 "%s"' % dataLocal
   #came out of loop
    conn.close()

def Function2():
       # Send data
       message = '0'
       print >>sys.stderr, 'sending function 2 message"%s"' % message
       sock.sendall(message)
       data = sock.recv(160)
       print >>sys.stderr, 'Server Data Function 2 "%s"' % data
   # Receiving from client
   # wait to accept a connection - blocking call
   conn, addr = sockLocal.accept()
   print 'Connected with ' + addr[0] + ':' + str(addr[1])
        dataLocal = conn.recv(1024)   
   print >>sys.stderr, 'Socket Data Function 2 "%s"' % dataLocal
   #came out of loop
    conn.close()
 
# Call functions
Function1()
time.sleep(1)
Function2()
time.sleep(1)
Function1()
time.sleep(1)
Function2()


Output is

Code: Select allmiji@Momiji:~$ sudo ./client.py
connecting to 192.168.4.1 port 80
sending function 1 message "0"
Server Data Function 1 "Recieved"
Connected with 192.168.4.1:4109
Socket Data Function 1 "Step 1"
sending function 2 message"0"
Server Data Function 2 "Recieved"
Connected with 192.168.4.1:4110
Socket Data Function 2 "Step 1"
sending function 1 message "0"
Server Data Function 1 "Recieved"
Connected with 192.168.4.1:4111
Socket Data Function 1 "Step 1"
sending function 2 message"0"
Server Data Function 2 "Recieved"
Connected with 192.168.4.1:4112
Socket Data Function 2 "Step 1


I haven't tested this in terms of time so not sure if it may lead to memory slowing depleting due to constant connections and closing etc.

Kind Regards

Cdr
User avatar
By raz123
#7520 How about a function interpreter on the ESP that is directly fed by the browser's url request?

Let me explain: suppose that your ESP runs an http server on 192.168.1.100.
In your browser, you would write: http://192.168.1.100/run/[terminal commands here] for a direct dynamic input.

eg: http://192.168.1.100/run/dofile("test.lua")


Alternatively, what about preconfigured urls that would execute certain functions?

eg: Going to http://192.168.1.100/function1 would execute function1() of your lua code.

Thoughts?