This is the client NodeMCU code called client.lua and it runs on the client device.
-- Basement Client Switch
-- This code runs a simple toggle switch where it sends a udp "toggle"
-- command to the basement relay.
-- The hardest part is discovery of which IP address to send to.
-- To do this we simply send out a broadcast message for now.
M = {}
M.port = 8988
M.myip = nil
M.sock = nil
M.isInitted = false
local pin, pulse1
pin = 5
pulse1 = tmr.now()
gpio.mode(pin, gpio.INT, gpio.PULLUP)
function pin1cb(level)
local pulse2 = tmr.now()
M.sendCustomBroadcast("toggle")
print("Switched", level, pulse2 - pulse1 )
pulse1 = pulse2
-- gpio.trig(pin, level == gpio.HIGH and "down" or "up")
gpio.trig(pin, "both")
end
gpio.trig(pin, "both", pin1cb)
print("setup trigger")
ledState = gpio.LOW
ledCtr = 0
ledCurrentCnt = 0
function blinkLed(ctr)
local pin = 4
ledCtr = ctr
ledCurrentCnt = 0
gpio.mode(pin, gpio.OUTPUT)
tmr.alarm(6, 100, tmr.ALARM_AUTO, blinkLedCallback)
end
function blinkLedCallback()
print("blink", ledCurrentCnt, ledCtr)
if ledCurrentCnt >= ledCtr then
print("Stopping LED blink")
tmr.stop(6)
gpio.write(4, gpio.HIGH)
return
end
if ledState == gpio.LOW then
ledState = gpio.HIGH
else
ledState = gpio.LOW
end
gpio.write(4, ledState)
ledCurrentCnt = ledCurrentCnt + 1
end
blinkLed(6)
function M.init()
print("Initting...")
M.sock = net.createConnection(net.UDP, 0)
M.myip = wifi.sta.getip()
if M.myip == nil then
print("You need to connect to wifi. Unable to init.")
else
print("My IP: " .. M.myip)
M.isInitted = true
end
end
function M.setupWifi()
-- setwifi
wifi.setmode(wifi.STATION)
-- longest range is b
wifi.setphymode(wifi.PHYMODE_B)
--Connect to access point automatically when in range
wifi.sta.config("NETGEAR-main", "blah")
wifi.sta.connect()
--register callback
wifi.sta.eventMonReg(wifi.STA_IDLE, function() print("STATION_IDLE") end)
--wifi.sta.eventMonReg(wifi.STA_CONNECTING, function() print("STATION_CONNECTING") end)
wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() print("STATION_WRONG_PASSWORD") end)
wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() print("STATION_NO_AP_FOUND") end)
wifi.sta.eventMonReg(wifi.STA_FAIL, function() print("STATION_CONNECT_FAIL") end)
wifi.sta.eventMonReg(wifi.STA_GOTIP, M.gotip)
--register callback: use previous state
wifi.sta.eventMonReg(wifi.STA_CONNECTING, function(previous_State)
if(previous_State==wifi.STA_GOTIP) then
print("Station lost connection with access point\n\tAttempting to reconnect...")
else
print("STATION_CONNECTING")
end
end)
--start WiFi event monitor with default interval
wifi.sta.eventMonStart(1000)
end
function M.gotip()
print("STATION_GOT_IP")
M.myip = wifi.sta.getip()
print("My IP: " .. M.myip)
M.init()
blinkLed(10)
-- M.initUdpServer()
-- M.initTcpServer()
M.sendCustomBroadcast("toggle")
end
function M.sendCustomBroadcast(msg)
if M.isInitted == false then
print("You must init first.")
return
end
local bip = wifi.sta.getbroadcast()
--print("Broadcast addr:" .. bip)
print("Sending msp to ip: " .. bip .. " " .. msg)
M.sock:connect(M.port, bip)
M.sock:send(msg)
M.sock:close()
end
M.setupWifi()
--M.init()
This is the server code, i.e. the device running the relay.
This is the basement_main.lua file for the server.
-- Main entry file for Basement Relay
-- We include the basement_relay file which is the object that controls the Relay
-- We include the basement_udp file which is the UDP server where we listen for on/off commands
server = require("basement_udp")
relay = require("basement_relay")
server.setupWifi()
server.init()
function onUdpCallback(msg)
if msg then
print("Got udp msg:" .. msg)
if msg == "on" then
relay.on()
elseif msg == "off" then
relay.off()
elseif msg == "toggle" then
relay.toggle()
else
print("got cmd do not understand")
end
else
print("Got nil udp msg")
end
end
server.registerCallbackOnUdpRecv(onUdpCallback)
This is the basement_relay code for the server.
-- Toggle Relay
local M = {}
M = {}
M.pin = 5
M.isOn = false
M.isInitted = false
function M.init()
if M.isInitted then return end
-- setup led as output and turn on
gpio.mode(M.pin, gpio.OUTPUT) --, gpio.PULLUP)
M.isInitted = true
print("Initted LED. pin: " .. M.pin)
end
function M.on()
M.init()
gpio.write(M.pin, gpio.LOW)
M.isOn = true
print("Turned LED on. pin: " .. M.pin)
end
function M.off()
M.init()
gpio.write(M.pin, gpio.HIGH)
M.isOn = false
print("Turned LED off. pin: " .. M.pin)
end
function M.toggle()
if M.isOn then
M.off()
else
M.on()
end
end
return M
-- relay = M
-- led.on()
-- tmr.alarm(0, 4000, tmr.ALARM_AUTO, relay.toggle)
This is basement_udp.lua
-- UDP Hello Announce v3
--local M = {}
M = {}
M.port = 8988
M.myip = nil
M.sock = nil
M.callbackOnUdpRecv = nil -- a callback can be registered so that when we recv udp data we will call your method
--M.announce =
M.isInitted = false
function M.init()
print("Initting...")
M.sock = net.createConnection(net.UDP, 0)
M.myip = wifi.sta.getip()
if M.myip == nil then
print("You need to connect to wifi. Unable to init.")
else
print("My IP: " .. M.myip)
M.isInitted = true
end
end
function M.createAnnounce(jsonTagTable)
-- see if there is a jsontagtable passed in as extra meta
local jsontag = ""
if jsonTagTable ~= nil then
ok, jsontag = pcall(cjson.encode, jsonTagTable)
if ok then
--print("Adding jsontagtable" .. jsontag)
else
print("failed to encode jsontag!")
end
end
local a = {}
a.Announce = "i-am-a-client"
a.Widget = "com-chilipeppr-widget-basementrelay"
a.MyDeviceId = "chip:" .. node.chipid() .. "-flash:" .. node.flashid() .. "-mac:" .. wifi.sta.getmac()
a.JsonTag = jsontag
local ok, json = pcall(cjson.encode, a)
if ok then
--print("Encoded json for announce: " .. json)
else
print("failed to encode json!")
end
return json
end
-- send announce to broadcast addr so spjs
-- knows of our existence
function M.sendBroadcast()
if M.isInitted == false then
print("You must init first.")
return
end
local bip = wifi.sta.getbroadcast()
--print("Broadcast addr:" .. bip)
local annStr = M.createAnnounce()
print("Sending announce to ip: " .. bip .. " " .. annStr)
M.sock:connect(M.port, bip)
M.sock:send(annStr)
M.sock:close()
end
function M.setupWifi()
-- setwifi
wifi.setmode(wifi.STATION)
-- longest range is b
wifi.setphymode(wifi.PHYMODE_B)
--Connect to access point automatically when in range
wifi.sta.config("NETGEAR-main", "blah")
wifi.sta.connect()
--register callback
wifi.sta.eventMonReg(wifi.STA_IDLE, function() print("STATION_IDLE") end)
--wifi.sta.eventMonReg(wifi.STA_CONNECTING, function() print("STATION_CONNECTING") end)
wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() print("STATION_WRONG_PASSWORD") end)
wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() print("STATION_NO_AP_FOUND") end)
wifi.sta.eventMonReg(wifi.STA_FAIL, function() print("STATION_CONNECT_FAIL") end)
wifi.sta.eventMonReg(wifi.STA_GOTIP, M.gotip)
--register callback: use previous state
wifi.sta.eventMonReg(wifi.STA_CONNECTING, function(previous_State)
if(previous_State==wifi.STA_GOTIP) then
print("Station lost connection with access point\n\tAttempting to reconnect...")
else
print("STATION_CONNECTING")
end
end)
--start WiFi event monitor with default interval
wifi.sta.eventMonStart(1000)
end
function M.gotip()
print("STATION_GOT_IP")
M.myip = wifi.sta.getip()
print("My IP: " .. M.myip)
M.init()
M.initUdpServer()
M.initTcpServer()
M.sendBroadcast()
end
function M.sendinit()
-- we need to send a UDP announce packet to every IP
-- on the subnet to let any possible SPJS know we are
-- available
-- iterate thru entire subnet
M.ipctr = 1
tmr.alarm(6, 200, tmr.ALARM_SINGLE, M.sendNextHello)
end
function M.sendNextHello()
local i, j = string.find(M.myip, "%.%d+$")
local prefix = string.sub(M.myip, 0, i)
local ip = prefix .. M.ipctr
print("Sending announce to ip: " .. ip)
M.sock:connect(M.port, ip)
M.sock:send(M.announce)
M.sock:close()
M.ipctr = M.ipctr + 1
if M.ipctr < 25 then
tmr.alarm(6, 50, tmr.ALARM_SINGLE, M.sendNextHello)
end
end
function M.initUdpServer()
M.udpServer = net.createServer(net.UDP)
--M.udpServer:on("connection", M.onUdpConnection)
M.udpServer:on("receive", M.onUdpRecv)
M.udpServer:listen(M.port)
print("UDP Server started on port " .. M.port)
end
function M.onUdpConnection(sck)
print("UDP connection.")
--ip, port = sck:getpeer()
--print("UDP connection. from: " .. ip)
end
function M.registerCallbackOnUdpRecv(callback)
M.callbackOnUdpRecv = callback
end
function M.onUdpRecv(sck, data)
print("UDP Recvd. data: " .. data)
if M.callbackOnUdpRecv then
M.callbackOnUdpRecv(data)
end
end
function M.initTcpServer()
M.tcpServer = net.createServer(net.TCP)
M.tcpServer:listen(M.port, M.onTcpListen)
print("TCP Server started on port " .. M.port)
end
function M.onTcpListen(conn)
conn:on("receive", M.onTcpRecv)
end
function M.onTcpConnection(sck)
print("TCP connection.")
--ip, port = sck:getpeer()
--print("UDP connection. from: " .. ip)
end
function M.onTcpRecv(sck, data)
local peer = sck:getpeer()
print("TCP Recvd. data: " .. data .. ", Peer:" .. peer)
end
return M
-- M.setupWifi()
-- M.init()
--M.initServer()
--M.sendBroadcast()
-- function sampleOnUdpCallback(msg)
-- print("Got udp msg:" .. msg)
-- end
-- M.registerCallbackOnUdpRecv(sampleOnUdpCallback)
No comments:
Post a Comment