[SOLVED][Edge] Need help to implement UDP server with cosock

Hello, I’m new with lua and Edge driver. As a start, I wrote a simple driver based on ESP8266 Sample Driver, using UDP, but there is a error.

2022-03-08T05:51:49.462837524+00:00 INFO Dummy Driver  SERVER start
2022-03-08T05:51:49.489851524+00:00 INFO Dummy Driver  SERVER running on 192.168.100.6:53053
2022-03-08T05:51:49.500790857+00:00 FATAL Dummy Driver  Lua: runtime error: [string "cosock/socket/internals.lua"]:56: attempt to index a nil value (field 'wakers')
stack traceback:
	[string "cosock/socket/internals.lua"]:56: in method 'receivefrom'
	[string "server.lua"]:18: in field 'start'
	[string "init.lua"]:58: in main chunk

My code is looks like:

server.lua

local log = require "log"
local socket = require('cosock').socket

local server = {}

function server.start(driver)
    log.info("SERVER start")
    local sock = assert(socket.udp())

    local ok, err = sock:setsockname("*", 0)
    if not ok then
        log.error("failed to bind server: " .. err)
        return
    end
    log.info(string.format("SERVER running on %s:%s", sock:getsockname()))

    while true do
        local buf, ip, port = sock:receivefrom() --> THIS LINE TRIGGER ERROR
        print(buf, ip, port)
    end
end

return server

And use the server

init.lua

--- smartthings libraries
local Driver = require "st.driver"
local capabilities = require "st.capabilities"
local log = require "log"

--- local modules
local server = require "server"

local function device_added(driver, device)
    log.info("[" .. device.id .. "] Adding new Hello World device")
    device:emit_event(capabilities.switch.switch.on())
end

local function device_init(driver, device)
    log.info("[" .. device.id .. "] Initializing Hello World device")
    device:online()
end

local function device_removed(driver, device)
    log.info("[" .. device.id .. "] Removing Hello World device")
end

local function command_handler(driver, device, command)
end


local driver = Driver("Empty Driver", {
    discovery = function (driver, _)
        driver:try_create_device({
            type = "LAN",
            device_network_id = "hello thing",
            label = "Hello World Device",
            profile = "hello-world.v1",
            manufacturer = "SmartThings",
            model = "v1",
            vendor_provided_label = nil
        })
    end,
    lifecycle_handlers = {
        added = device_added,
        init = device_init,
        removed = device_removed
    },
    capability_handlers = {
        [capabilities.switch.ID] = {
            [capabilities.switch.commands.on.NAME] = command_handler,
            [capabilities.switch.commands.off.NAME] = command_handler,
        },
    },
})

server.start(driver)

driver:run()

What is matter with this code?

Hi, @cmsong-shina. Are you still receiving this error?

No, I found a solution.

It was a miss understanding about cosock module.

It can be solved by wrap with cosock.spawn.

local log = require "log"
+local cosock = require("cosock")
+local socket = cosock.socket
-local socket = require('cosock').socket

local server = {}

function server.start(driver)
+   cosock.spawn(function ()
        log.info("SERVER start")
        local sock = assert(socket.udp())

        local ok, err = sock:setsockname("*", 0)
        if not ok then
            log.error("failed to bind server: " .. err)
            return
        end
        log.info(string.format("SERVER running on %s:%s", sock:getsockname()))

        while true do
            local buf, ip, port = sock:receivefrom() --> THIS LINE TRIGGER ERROR
            print(buf, ip, port)
        end
+   end)
end

return server

Awesome! Thank you for sharing your solution :smiley: