About This Project
The script is designed for Air202 on the S6 board and the module version with the solar battery charging system (diagram on the attached photo). For the version with CN3065 chip, we can connect the solar panel, which in combination with the module susceptibility will significantly extend its working time.
What’s Connected
Instruction
The scripts below are based on source files. All source files are found here.
A description of the installation of scripts and basic software can be found here Moduł GSM Air202 - opis instalacji oprogramowania - elektroda.pl
Preparation of scripts for installation
1. From the Luat_2G_RDA_8955/script_LuaTask/lib/ directory, open the link.lua file in the text editor and enter the access data for your network in the following function.
function setAPN (apn, user, pwd)
apnname, username, password = “internet”, “internet”, “internet”
end
2. Open the mqttTask.lua file in the text editor and enter the configuration data from your Cayenne IoT panel.
c_username = “ce263200-1682-11e9-a08c-c5a286f8c00d”
c_password = “b25e852397da440628babd9bf4198fec6870da91”
c_clientid = “327c5f30-28a4-11e9-8cb9-732fc93af22b”
3. In the file mqttTask.lua you can set the time (ms) to send the following data to the Cayenne IoT.
send_temp = 30000
send_hum = 32000
send_batt = 50000
send_rssi = 42000
4. In the file mqttOutMsg.lua you can choose which data you want to send to Cayenne IoT. By default, the script sends battery voltage and rssi. Temperature and humidity will be sent after removing “–” from “-- pubQos0Test()” and “-- pubQos1Test()”. If you do not use BME280, do not delete “–” because the script will report an error.
function init()
– Publish temperature
– pubQos0Test()
– Publish humidity
– pubQos1Test()
– Publish battery voltage
pubQos2Test()
– Publish rssi
pubQos3Test()
end
5. Download the basic software DEFAULT_2.0.0_Luat_V0033_Air202 into the module.
6. Upload all files from the Luat_2G_RDA_8955/script_LuaTask/lib/ directory to the module.
7. Upload the changed files main.lua, mqttInMsg.lua, mqttOutMsg.lua and mqttTask.lua to the module.
8. The connection of the BME280 and the relay with Air202 is shown in the attached photos.
9. Restart the module and go to the configuration settings in the Cayenne IoT panel to add the switch on channel 5 and widgets.
Scripts
main.lua
-- PROJECT and VERSION variables must be defined at this location
-- PROJECT: ascii string type, can be defined casually, as long as it is not used,
-- VERSION: ascii string type, if you use the Luat IoT cloud platform firmware upgrade function, you must follow the definition of "X.X.X", X means 1 digit; otherwise you can define it casually
PROJECT = "MQTT"
VERSION = "2.0.0"
-- Load the log function module and set the log output level
-- If you close the log that is output from the log module interface, the level is set to log.LOG_SILENT
require "log"
LOG_LEVEL = log.LOGLEVEL_TRACE
--[[
If you use the UART output log, open the code "--log.openTrace(true,1,115200)" in this line, and modify the parameters of this interface according to your needs.
If you want to completely close the output log in the script (including calling the log module interface and the log output from the Lua standard print interface), execute log.openTrace (false, the second parameter is the same as the second parameter that calls the openTrace interface to open the log). E.g:
1, did not call sys.opntrace configuration log output port or the last time is to log.openTrace (true, nil, 921600) configuration log output port, at this time to close the output log, directly call log.openTrace (false)
2, the last time is to call log.openTrace (true, 1, 115200) to configure the log output port, at this time to close the output log, directly call log.openTrace (false, 1)
]]
-- log.openTrace(true,1,115200)
require "sys"
require "net"
-- Query the GSM signal strength every 1 minute
-- Query base station information every 1 minute
net.startQueryAll(60000, 60000)
-- Load console debugging function module (here code is uart1, baud rate 115200)
-- This function module is not required, depending on the project requirements, whether to load or not
-- Note when using: uart used by the console should not conflict with uart used by other functions.
-- For instructions, refer to "console function instructions.docx" under demo/console
-- require "console"
-- console.setup(1, 115200)
-- Load hardware watchdog function module
-- According to your own hardware configuration: 1, whether to load this function module; 2, configure the Luat module to reset the microcontroller pins and feed the dog pins
-- The Air201 development board sold by Hezhou has a hardware watchdog, so this function module must be loaded when using the official Air201 development board.
require "wdt"
wdt.setup(pio.P0_30, pio.P0_31)
-- Set GPIO 29 as an output
-- Set GPIO 29 low
pio.pin.setdir(pio.OUTPUT, pio.P0_29)
pio.pin.setval(0, pio.P0_29)
-- Load network indicator function module
-- According to your own project needs and hardware configuration: 1, whether to load this function module; 2, configuration indicator pin
-- The indicator pins on the Air800 and Air801 development boards sold by Hezhou are pio.P0_28, and the indicator pins on other development boards are pio.P1_1
--require "netLed"
--netLed.setup(true,pio.P1_1)
-- In the network indicator function module, the blinking rule of the indicator light under various working conditions is configured by default. Refer to the default value of ledBlinkTime configuration in netLed.lua.
-- If the default value does not meet the requirements, call netLed.updateBlinkTime here to configure the blinking duration.
-- Load error log management function module [It is strongly recommended to open this function]
-- The following 2 lines of code, just a simple demonstration of how to use the errDump function, see the errDump api for details
-- require "errDump"
-- errDump.request("udp://ota.airm2m.com:9072")
-- Load remote upgrade function module [strongly recommended to open this function]
-- The following 3 lines of code, just a simple demonstration of how to use the update function, refer to the update api and demo/update for details.
-- PRODUCT_KEY = "v32xEAKsGTIEQxtqgwCldp5aPlcnPs3K"
-- require "update"
-- update.request()
-- Load MQTT function test module
require "mqttTask"
-- Start system framework
sys.init(0, 0)
sys.run()
mqttInMsg.lua
-- Module function: MQTT client data receiving processing
-- @author openLuat
-- @module mqtt.mqttInMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
module(...,package.seeall)
-- MQTT client data receiving processing
-- @param mqttClient, MQTT client object
-- @return processing returns true, processing error returns false
-- @usage mqttInMsg.proc(mqttClient)
function proc(mqttClient)
local result,data
while true do
result,data = mqttClient:receive(2000)
-- Received data
if result then
log.info("mqttInMsg.proc",data.topic,string.toHex(data.payload))
-- TODO: Process data.payload according to your own requirements
if string.sub(data.topic, 89,89) == "5" then
str_rec = string.sub(data.payload, 1,15)
str_sta = string.sub(data.payload, 17,17)
mqttOutMsg.pubQos4Test()
end
-- If there is data waiting to be sent in mqttOutMsg, exit this loop immediately
if mqttOutMsg.waitForSend() then return true end
else
break
end
end
return result or data=="timeout"
end
mqttOutMsg.lua
-- Module function: MQTT client data transmission processing
-- @author openLuat
-- @module mqtt.mqttOutMsg
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
--[[Temperature and humidity are read on the basis of the data sheet provided by Bosch for the Bme280 environmental sensor.
The sensor calibration code is based on algorithms provided by Bosch.]]
module(...,package.seeall)
-- message queue for data transmission
local msgQueue = {}
local function insertMsg(topic,payload,qos,user)
table.insert(msgQueue,{t=topic,p=payload,q=qos,user=user})
end
local function pubQos0TestCb(result)
log.info("mqttOutMsg.pubQos0TestCb",result)
if result then sys.timerStart(pubQos0Test,mqttTask.send_temp) end
end
function pubQos0Test()
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/1","temp,c=" .. string.sub(readTemHum(),6,10),1,{cb=pubQos0TestCb})
end
local function pubQos1TestCb(result)
log.info("mqttOutMsg.pubQos1TestCb",result)
if result then sys.timerStart(pubQos1Test,mqttTask.send_hum) end
end
function pubQos1Test()
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/2","rel_hum,p=" .. string.sub(readTemHum(),20,24),1,{cb=pubQos1TestCb})
end
local function pubQos2TestCb(result)
log.info("mqttOutMsg.pubQos2TestCb",result)
if result then sys.timerStart(pubQos2Test,mqttTask.send_batt) end
end
function pubQos2Test()
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/3","batt,v=" .. misc.getVbatt(),1,{cb=pubQos2TestCb})
end
local function pubQos3TestCb(result)
log.info("mqttOutMsg.pubQos3TestCb",result)
if result then sys.timerStart(pubQos3Test,mqttTask.send_rssi) end
end
function pubQos3Test()
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/4","rssi,dbm=" .. net.getRssi(),1,{cb=pubQos3TestCb})
end
local function pubQos4TestCb(result)
log.info("mqttOutMsg.pubQos4TestCb",result)
end
-- Set the switch
function pubQos4Test()
if mqttInMsg.str_sta == "1" then
print("switch on")
-- Set GPIO 29 high
pio.pin.sethigh(pio.P0_29)
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/5","1",1,{cb=pubQos4TestCb})
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/response", "ok," .. string.sub(mqttInMsg.str_rec, 1,15),1,{cb=pubQos4TestCb})
elseif mqttInMsg.str_sta == "0" then
print("switch off")
-- Set GPIO 29 low
pio.pin.setlow(pio.P0_29)
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/5","0",1,{cb=pubQos4TestCb})
insertMsg("v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/response", "ok," .. string.sub(mqttInMsg.str_rec, 1,15),1,{cb=pubQos4TestCb})
end
end
-- Initialize "MQTT client data transmission"
-- @return none
-- @usage mqttOutMsg.init()
function init()
-- Publish temperature
--pubQos0Test()
-- Publish humidity
--pubQos1Test()
-- Publish battery voltage
pubQos2Test()
-- Publish rssi
pubQos3Test()
end
-- To initialize "MQTT client data transmission"
-- @return none
-- @usage mqttOutMsg.unInit()
function unInit()
sys.timerStop(pubQos0Test)
sys.timerStop(pubQos1Test)
while #msgQueue>0 do
local outMsg = table.remove(msgQueue,1)
if outMsg.user and outMsg.user.cb then outMsg.user.cb(false,outMsg.user.para) end
end
end
-- Does the MQTT client have data waiting to be sent?
-- @return returns true if data is waiting to be sent, otherwise returns false
-- @usage mqttOutMsg.waitForSend()
function waitForSend()
return #msgQueue > 0
end
-- MQTT client data transmission processing
-- @param mqttClient, MQTT client object
-- @return processing returns true, processing error returns false
-- @usage mqttOutMsg.proc(mqttClient)
function proc(mqttClient)
while #msgQueue>0 do
local outMsg = table.remove(msgQueue,1)
local result = mqttClient:publish(outMsg.t,outMsg.p,outMsg.q)
if outMsg.user and outMsg.user.cb then outMsg.user.cb(result,outMsg.user.para) end
if not result then return end
end
return true
end
-- Read the temperature and humidity from bme280
function readTemHum()
local str_tem
local function init(data)
local i2cslaveaddr = 0x76
if i2c.setup(2,i2c.SLOW, i2cslaveaddr) ~= i2c.SLOW then
print("init fail")
return
end
i2c.write(2, 0xF2, 0x01)
i2c.write(2, 0xF4, 0x25)
i2c.write(2, 0xF5, 0x00)
-- Temperature
dig_T1 = bit.bor(bit.lshift(string.byte(i2c.read(2,0x89,1)),8), string.byte(i2c.read(2,0x88,1)))
dig_T2 = bit.bor(bit.lshift(string.byte(i2c.read(2,0x8B,1)),8), string.byte(i2c.read(2,0x8A,1)))
dig_T3 = bit.bor(bit.lshift(string.byte(i2c.read(2,0x8D,1)),8), string.byte(i2c.read(2,0x8C,1)))
adc_T = bit.bor(bit.lshift(string.byte(i2c.read(2,0xFA,1)),12), bit.lshift(string.byte(i2c.read(2,0xFB,1)),4), bit.lshift(string.byte(i2c.read(2,0xFC,1)),4))
var1 = bit.arshift((bit.arshift(adc_T,3) - bit.lshift(dig_T1,1)) * dig_T2,11)
var2 = bit.arshift((bit.arshift((bit.arshift(adc_T,4) - dig_T1) * (bit.arshift(adc_T,4) - dig_T1),12)) * dig_T3,14)
t_fine = var1 + var2
T = bit.arshift(t_fine * 5 + 128,8)
-- Humidity
dig_H1 = string.byte(i2c.read(2,0xA1,1))
dig_H2 = bit.bor(bit.lshift(string.byte(i2c.read(2,0xE2,1)),8), string.byte(i2c.read(2,0xE1,1)))
dig_H3 = string.byte(i2c.read(2,0xE3,1))
dig_H4 = bit.bor(bit.lshift(string.byte(i2c.read(2,0xE4,1)),4), bit.band(string.byte(i2c.read(2,0xE5,1)),0xF))
dig_H5 = bit.bor(bit.lshift(string.byte(i2c.read(2,0xE6,1)),4), bit.rshift(string.byte(i2c.read(2,0xE5,1)),4))
dig_H6 = string.byte(i2c.read(2,0xE7,1))
adc_H = bit.bor(bit.lshift(string.byte(i2c.read(2,0xFD,1)),8), string.byte(i2c.read(2,0xFE,1)))
v_x1_u32r = (t_fine - (76800))
v_x1_u32r = (bit.arshift(((bit.lshift(adc_H,14) - bit.lshift((dig_H4),20) - ((dig_H5) * v_x1_u32r)) + (16384)),15) * bit.arshift(((bit.arshift((bit.arshift((v_x1_u32r * (dig_H6)),10) * (bit.arshift((v_x1_u32r * (dig_H3)),11) + (32768))),10) + (2097152)) * (dig_H2) + 8192),14))
v_x1_u32r = (v_x1_u32r - bit.arshift((bit.arshift((bit.arshift(v_x1_u32r,15) * bit.arshift(v_x1_u32r,15)),7) * (dig_H1)),4))
if v_x1_u32r < 0 then
v_x1_u32r = 0
end
if v_x1_u32r > 419430400 then
v_x1_u32r = 419430400
end
-- String temperature and humidity
str_tem = "tem: " .. string.sub(T,1,2) .. "." .. string.sub(T,3,4) .. "*C " .. " hum: " .. string.sub(bit.arshift(bit.arshift(v_x1_u32r,12) * 1000, 10),1,2) .. "." .. string.sub(bit.arshift(bit.arshift(v_x1_u32r,12) * 1000, 10),3,4) .. "%"
io.write(str_tem, "\n")
end
init()
i2c.close(2)
return str_tem
end
mqttTask.lua
-- Module function: MQTT client processing framework
-- @author openLuat
-- @module mqtt.mqttTask
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.28
module(...,package.seeall)
require"misc"
require"mqtt"
require"mqttOutMsg"
require"mqttInMsg"
-- Enter the username, password and client id from the Cayenne configuration page
c_username = "5c37e060-2ea8-11e9-9c33-75e6b356cec4"
c_password = "4ee24ceeae4d5c88babbcf95aa93a5e72b444165"
c_clientid = "7c91e3b0-2ea8-11e9-9c33-75e6b356cec4"
-- Set the time (ms) for publication of temperature, humidity, battery voltage and rssi
send_temp = 30000
send_hum = 32000
send_batt = 50000
send_rssi = 42000
local ready = false
-- Is the MQTT connection active?
-- @return returns true if activated, false returns if inactive
-- @usage mqttTask.isReady()
function isReady()
return ready
end
-- Start the MQTT client task
sys.taskInit(
function()
local retryConnectCnt = 0
while true do
if not socket.isReady() then
retryConnectCnt = 0
-- Wait for the network environment to be ready, the timeout is 5 minutes
sys.waitUntil("IP_READY_IND",300000)
end
if socket.isReady() then
local imei = misc.getImei()
-- Create an MQTT client
local mqttClient = mqtt.client(c_clientid,nil,c_username,c_password)
-- Block execution of the MQTT CONNECT action until successful
-- If you use ssl connection, open mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"}), configure according to your needs
-- mqttClient:connect("lbsmqtt.airm2m.com",1884,"tcp_ssl",{caCert="ca.crt"})
if mqttClient:connect("mqtt.mydevices.com",1883,"tcp") then
retryConnectCnt = 0
ready = true
-- Subscription theme
if mqttClient:subscribe({
-- ["v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/1"]=1,
-- ["v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/2"]=1,
-- ["v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/3"]=1,
-- ["v1/" .. mqttTask.c_username .. "/things/" .. mqttTask.c_clientid .. "/data/4"]=1,
["v1/" .. c_username .. "/things/" .. c_clientid .. "/cmd/5"]=1
}) then
mqttOutMsg.init()
-- Loop processing received and sent data
while true do
if not mqttInMsg.proc(mqttClient) then log.error("mqttTask.mqttInMsg.proc error") break end
if not mqttOutMsg.proc(mqttClient) then log.error("mqttTask.mqttOutMsg proc error") break end
end
mqttOutMsg.unInit()
end
ready = false
else
retryConnectCnt = retryConnectCnt+1
end
-- Disconnect MQTT connection
mqttClient:disconnect()
if retryConnectCnt>=5 then link.shut() retryConnectCnt=0 end
sys.wait(5000)
else
-- Enter flight mode, after 20 seconds, exit flight mode
net.switchFly(true)
sys.wait(20000)
net.switchFly(false)
end
end
end
)
Instruction
Air202 - sending temperature, humidity, battery voltage and rssi to the Cayenne IoT cloud and relay control from the phone application.
The script is designed for Air202 on the S6 board and the module version with the solar battery charging system (diagram on the attached photo). For the version with CN3065 chip, we can connect the solar panel, which in combination with the module susceptibility will significantly extend its working time.
Instruction
The scripts below are based on source files. All source files are found here.
https://github.com/openLuat/Luat_2G_RDA_8955
A description of the installation of scripts and basic software can be found here.
https://www.elektroda.pl/rtvforum/viewtopic.php?p=17591692#17591692
Preparation of scripts for installation
1. From the Luat_2G_RDA_8955/script_LuaTask/lib/ directory, open the link.lua file in the text editor and enter the access data for your network in the following function.
function setAPN (apn, user, pwd)
apnname, username, password = "internet", "internet", "internet"
end
2. Open the mqttTask.lua file in the text editor and enter the configuration data from your Cayenne IoT panel.
c_username = "ce263200-1682-11e9-a08c-c5a286f8c00d"
c_password = "b25e852397da440628babd9bf4198fec6870da91"
c_clientid = "327c5f30-28a4-11e9-8cb9-732fc93af22b"
3. In the file mqttTask.lua you can set the time (ms) to send the following data to the Cayenne IoT.
send_temp = 30000
send_hum = 32000
send_batt = 50000
send_rssi = 42000
4. In the file mqttOutMsg.lua you can choose which data you want to send to Cayenne IoT. By default, the script sends battery voltage and rssi. Temperature and humidity will be sent after removing "--" from "-- pubQos0Test()" and "-- pubQos1Test()". If you do not use BME280, do not delete "--" because the script will report an error.
function init()
-- Publish temperature
-- pubQos0Test()
-- Publish humidity
-- pubQos1Test()
-- Publish battery voltage
pubQos2Test()
-- Publish rssi
pubQos3Test()
end
5. Download the basic software DEFAULT_2.0.0_Luat_V0033_Air202 into the module.
6. Upload all files from the Luat_2G_RDA_8955/script_LuaTask/lib/ directory to the module.
7. Upload the changed files main.lua, mqttInMsg.lua, mqttOutMsg.lua and mqttTask.lua to the module.
8. The connection of the BME280 and the relay with Air202 is shown in the attached photos.
9. Restart the module and go to the configuration settings in the Cayenne IoT panel to add the switch on channel 5 and widgets.
Triggers & Alerts
(Did you use the Triggers & Alerts feature?)
Scheduling
(Did you use the Scheduling feature?)
Dashboard Screenshots
Photos of the Project
(Take some pictures of your project functioning in the wild!)
Video
(Upload a YouTube video showcasing your project in action!)