欢迎图片

2 Script

Last modified by Joe on 2024/05/21 11:24

1 General Script Demo

1.1 Address Operation

Write/Read data from address A to BFor example:transfer D2 to D0

1624245865976-320.png

Depend on diffferent format of data.V-Box use different script functions.
for example. addr_setshort(addr,num) Function: Write 16-bit signed decimal address
addr_getshort(addr) Function:Read 16-bit signed decimal address
addr_getword(string addr)Function: Read 16-bit unsigned decimal address
More script function are in the second section of  “V-BOX Script Interface Manual”

1.2 Arithmetic

1624249623612-177.png

1.3 Set 100 to D0--D19

1624249693457-742.png

1.4 Short message

The following demo shows that when the alarm condition is reached: temp1 > 5 & temp2 >10 & temp3 < 20(lasts more than 5 seconds) , then send an "alarm trigger" sms. 

When the alarm condition is released,then send an  "alarm release" sms. Script is as below:

function sms.main()
------send condition------
local temp1 = addr_getword("@Temperature1")
local temp2 = addr_getword("@Temperature2")
local temp3 = addr_getword("@Temperature3")
local timer = addr_getword("@Timer")
local tag = addr_getbit("@Tag")
------lasting time------
if temp1 > 5 and temp2 > 10 and temp3 < 20 then
    timer = timer + 1
    addr_setword("@Timer",timer)
else
    timer = 0
    addr_setword("@Timer",timer)
end
------send sms & output Y0------
if timer > 5 then
   if tag == 0 then
        send_sms_ira("19859254700","alarm trigger")
        addr_setbit("@Tag",1)
   end
elseif tag == 1 then
send_sms_ira("19859254700","alarm release")
addr_setbit("@Tag",0)
end
end

1.5 Telegram notification

This example shows how to use the Bot API to send message into Telegram group or channel. When monitoring bit "@HDX" changes, it will trigger and send the message. Please replace with your own Token and chat id.

As for How to get the botToken and chatID, please check the following videos:

https://www.youtube.com/watch?v=zh6yYlnjX7k

https://www.youtube.com/watch?v=Pj8mwuMZZvg

If when you follow the second video to get chatID and there is a display like the following, you can change "getUpdates" to "deleteWebhook" to solve in website.
 

6Z7mdnm13p.png

WjE1P2yxIA.png

After deleting Webhook, you can change to "getUpdates" and continue to follow the second video. 
 

zl6CJlwhER.png

Note: Bots added to Groups or Channels need to be provided with administrator rights.

1.Permissions

Bots added to Groups or Channels need to be provided with administrator rights. For example "joe" is bot I created.
 

3GS3dP01Wx.png

eEyv361VZs.png

2.URL check

You can use the URL to test the status of a group or channel.

 url = "https://api.telegram.org/bot"..telegramBotToken.."/sendMessage?text="..message.."&chat_id="..telegramChatID

telegram URL.png

3.Script

local tempBit = 0
local tempWord = 0

local botToken = "5504549693:AAEy6a5G-sOF3CINONxMNABeYnoS4ABVlfg"
local chatID = "-641959124"--The chat id from Channel or Group

local https = require("https")
local json = require("json")

-- Send http.get request and return response result
function getHttpsUrl(url)
   local body = {}
   local bodyJson = json.encode(body)
   local header = {}
    header["content-type"] = "application/json"
local result_table, code, headers, status = https.request(url, bodyJson)
print("code:"..code)
if code~= 200 then
 return
else
 return body
end
end

function sendAlarm(telegramBotToken, message, telegramChatID)
   local url = "https://api.telegram.org/bot"..telegramBotToken.."/sendMessage?text="..message.."&chat_id="..telegramChatID
   --local url = 'http://v-box.net'
   --local url = 'https://www.google.com/'
   print("Get the link:"..url)
    getHttpsUrl(url)
end


function AlarmNotificate.main()
   local bitValue = addr_getbit("@HDX");
   local message = ''
   print("b=="..bitValue)
   if bitValue == 1 and bitValue ~= tempBit then
        message = 'Alarm triggered, the monitoring point test value is '.. bitValue
        sendAlarm(botToken, message, chatID)
       print("Notification pushed of triggering alarm,"..bitValue)
   elseif bitValue == 0 and bitValue ~= tempBit then
        message = 'Alarm dismissed, the monitoring point test value is '.. bitValue
        sendAlarm(botToken, message, chatID)
       print("Notification pushed of dismissing alarm,"..bitValue)
   end
    tempBit = bitValue----Prevent monitoring values from continuous being sent to the platform
   
   local wordValue = addr_getword("@HDW10")
   print("w=="..wordValue)
   --dosomething
   if wordValue >= 100 and wordValue ~= tempWord and tempWord <= 100 then
        message = 'Word alarm triggered, the word value is '.. wordValue
        sendAlarm(botToken, message, chatID)
       print("Notification pushed of triggering alarm,"..wordValue)
   elseif wordValue < 100 and wordValue ~= tempWord and tempWord >= 100 then
        message = 'Word alarm dismissed, the word value is '.. wordValue
        sendAlarm(botToken, message, chatID)
       print("Notification pushed of dismissing alarm,"..wordValue)
   end
    tempWord = wordValue----Prevent monitoring values from continuous being sent to the platform
end

1715678008611-743.png

Note: The name of script must be the same as the main function.

1.6 LINE Notify

This example shows how to use the LINE Notify to send message into LINE group. When monitoring bit "@test" changes, it will trigger and send the message. Please replace with your own Token.

local tempBit = 0
local tempWord = 0

local LineToken = "08XCpubkOdwGdGgRTXF0x8umiyrALtoM0v6lBFUV6PC"

local https = require("https")
local json = require("json")
local ltn12 = require("ltn12")

-- Send http.get request and return response result
function getHttpsUrl(url,header,reqbody)
   local body = {}
   local bodyJson = json.encode(body)
   local result_table, code, headers, status = https.request{
        method = "POST",
        url = url,
        source = ltn12.source.string(reqbody),
        headers = header,
        sink = ltn12.sink.table(body)
   }
   print("code:"..code)
   if code~= 200 then
       return
   else
       return body
   end
end

function getMessageUrl(lineMessage)
   local url = "https://notify-api.line.me/api/notify"
   local reqMess = "message="..lineMessage
   local headers =
                {
                        ["Authorization"] = "Bearer "..LineToken,
                        ["Content-Type"] = "application/x-www-form-urlencoded",
                        ["Content-Length"] = #reqMess
                }
   
   print("Get the link:"..url)
    getHttpsUrl(url, headers, reqMess)
end


function linenotify.main()
   local bitValue = addr_getbit("@test");
   local message = ''
   print("b=="..bitValue)
   if bitValue == 1 and bitValue ~= tempBit then
        message = 'Alarm V-Box triggered, the output is '.. bitValue
        getMessageUrl(message)
       print("Notification pushed of triggering alarm,"..bitValue)
   elseif bitValue == 0 and bitValue ~= tempBit then
        message = 'Alarm V-Box dismissed, the output is '.. bitValue
        getMessageUrl(message)
       print("Notification pushed of dismissing alarm,"..bitValue)
   end
    tempBit = bitValue----Prevent monitoring values from continuous being sent to the platform
   
   local wordValue = addr_getword("@t2")
   print("w=="..wordValue)
   --dosomething
   if wordValue >= 100 and wordValue ~= tempWord and tempWord <= 100 then
        message = 'Alarm V-Box triggered, the temperature is '.. wordValue
        getMessageUrl(message)
       print("Notification pushed of triggering alarm,"..wordValue)
   elseif wordValue < 100 and wordValue ~= tempWord and tempWord >= 100 then
        message = 'Alarm V-Box dismissed, the temperature is '.. wordValue
        getMessageUrl(message)
       print("Notification pushed of dismissing alarm,"..wordValue)
   end
    tempWord = wordValue----Prevent monitoring values from continuous being sent to the platform
end

1.7 Twilio WhatsApp Messaging

This example shows how to use the Twilio API to send WhatsApp message to private number. When monitoring bit "@testBit" changes, it will trigger and send the message. Please replace with your own SID, Token, twilioPhoneNumber and receiverPhoneNumber.

About how to register the Twilio API, please check the following video:

https://www.youtube.com/watch?v=Id4lKichauU

local tempBit = 0
local tempWord = 0

local https = require("https")
local json = require("json")
local ltn12 = require("ltn12")

local SID = 'AC1703bd710ffa98006d2bcc0b********'
local Token = 'd3c11897623c39e538b20263ec19****'

local twilioPhoneNumber = '+14155238886'
local receiverPhoneNumber = '+8615880018277'

local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
function encodingBase64(data)
   return ((data:gsub('.', function(x)
       local r,b='',x:byte()
       for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
       return r;
   end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
       if (#x < 6) then return '' end
       local c=0
       for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
       return b:sub(c+1,c+1)
   end)..({ '', '==', '=' })[#data%3+1])
end

function encodeUrl(str)
    str = string.gsub(str, "([^%w%.%- ])", function(c)
   return string.format("%%%02X", string.byte(c)) end)
   return string.gsub(str, " ", "+")
end




function requestBodySplice(message, sender, receiver)
   local reqBody = ''
   local encodeMess = encodeUrl(message)
   local encodeSend = encodeUrl(sender)
   local encodeRece = encodeUrl(receiver)
   --reqBody = "Body=Hello%20Wecon2&From=whatsapp%3A%2B14155238886&To=whatsapp%3A%2B8615880018277"
    reqBody = string.format("Body=%s&From=whatsapp:%s&To=whatsapp:%s", encodeMess, encodeSend, encodeRece)
   print(reqBody)
   return reqBody
end


-- Send http.get request and return response result
function getHttpsUrl(url,header,reqbody)
   local body = {}
   local bodyJson = json.encode(body)
   local result_table, code, headers, status = https.request{
        method = "POST",
        url = url,
        source = ltn12.source.string(reqbody),
        headers = header,
        sink = ltn12.sink.table(body)
   }
   print("code:"..code)
   if code~= 200 then
       return
   else
       return body
   end
end

function getMessageUrl(whatsAppMessage)
   local auth = SID..':'..Token
   local url = "https://api.twilio.com/2010-04-01/Accounts/"..SID.."/Messages"
   --local reqMess = "message="..twilioMessage
   local reqMess = requestBodySplice(whatsAppMessage, twilioPhoneNumber, receiverPhoneNumber)
   local headers =
                {
                        ["Authorization"] = "Basic "..encodingBase64(auth),
                        ["Content-Type"] = "application/x-www-form-urlencoded",
                        ["Content-Length"] = #reqMess
                }
   
   print("Get the link:"..url)
    getHttpsUrl(url, headers, reqMess)
end



function Twilio.main()
 --dosomething
 --local auth = SID..':'..Token
 --print(requestBodySplice("HelloWorld", twilioPhoneNumber, receiverPhoneNumber))
 --print(encodingBase64(auth))
 local bitValue = addr_getbit("@testBit");
   local message = ''
   print("b=="..bitValue)
   if bitValue == 1 and bitValue ~= tempBit then
        message = 'Alarm V-Box triggered, the output is '.. bitValue
        getMessageUrl(message)
       print("Notification pushed of triggering alarm,"..bitValue)
   elseif bitValue == 0 and bitValue ~= tempBit then
        message = 'Alarm V-Box dismissed, the output is '.. bitValue
        getMessageUrl(message)
       print("Notification pushed of dismissing alarm,"..bitValue)
   end
    tempBit = bitValue----Prevent monitoring values from continuous being sent to the platform
   
   local wordValue = addr_getword("@testWord")
   print("w=="..wordValue)
   --dosomething
   if wordValue >= 100 and wordValue ~= tempWord and tempWord <= 100 then
        message = 'Alarm V-Box triggered, the temperature is '.. wordValue
        getMessageUrl(message)
       print("Notification pushed of triggering alarm,"..wordValue)
   elseif wordValue < 100 and wordValue ~= tempWord and tempWord >= 100 then
        message = 'Alarm V-Box dismissed, the temperature is '.. wordValue
        getMessageUrl(message)
       print("Notification pushed of dismissing alarm,"..wordValue)
   end
    tempWord = wordValue----Prevent monitoring values from continuous being sent to the platform
end

1.8 HTTP response body

This example use https://www.weatherapi.com/ as example, to show how to parse value from HTTP response body. When we input the city name into address "@HDW5050":

InputHTTPparameter.png

Then the response body would be like as following:

{
   "location": {
       "name": "Madrid",
       "region": "Madrid",
       "country": "Spain",
       "lat": 40.4,
       "lon": -3.68,
       "tz_id": "Europe/Madrid",
       "localtime_epoch": 1669022636,
       "localtime": "2022-11-21 10:23"
    },
   "current": {
       "last_updated_epoch": 1669022100,
       "last_updated": "2022-11-21 10:15",
       "temp_c": 13.0,
       "temp_f": 55.4,
       "is_day": 1,
       "condition": {
           "text": "Partly cloudy",
           "icon": "//cdn.weatherapi.com/weather/64x64/day/116.png",
           "code": 1003
        },
       "wind_mph": 11.9,
       "wind_kph": 19.1,
       "wind_degree": 210,
       "wind_dir": "SSW",
       "pressure_mb": 1015.0,
       "pressure_in": 29.97,
       "precip_mm": 0.0,
       "precip_in": 0.0,
       "humidity": 88,
       "cloud": 75,
       "feelslike_c": 10.8,
       "feelslike_f": 51.4,
       "vis_km": 10.0,
       "vis_miles": 6.0,
       "uv": 3.0,
       "gust_mph": 22.1,
       "gust_kph": 35.6
    }
}

So we decode json into lua object to assign the value into addresses HDW6060(temperature), HDW7070(humidity), the code example like follows: 

local APIkey = '70faaecf926b4341b1974006221711'


local http = require("socket.http")
local json = require("json")

-- Send http.get request and return response result
function getHttpsUrl(url)
   local result_table, code, headers, status = http.request(url)
   print("code:"..code)
   if code~= 200 then
       return
   else
       return result_table
   end
end

function sendAPI(key, city)
   local url = "http://api.weatherapi.com/v1/current.json?key="..key.."&q="..city.."&aqi=no"
   --local url = 'http://v-box.net'
   --local url = 'https://www.google.com/'
   --http://api.weatherapi.com/v1/current.json?key=70faaecf926b4341b1974006221711&q=Barcelona&aqi=no
   print("Get the link:"..url)
   local body = getHttpsUrl(url)
   --print(body)
   local jsonBody = json.decode(body)
   --print(jsonBody["current"]["temp_c"])
   --print(type(jsonBody["current"]["temp_c"]))
   --print(type(jsonBody["current"]["humidity"]))
    addr_setfloat("@HDW6060", jsonBody["current"]["temp_c"])
    addr_setword("@HDW7070", jsonBody["current"]["humidity"])
end


function Weather.main()
   local cityName = addr_getstring("@HDW5050",6)
   print("cityName: "..cityName)
    sendAPI(APIkey, cityName)
end

1.9 High-Low Byte Switch

The following example is converting the floating number from order 1234 to order 3412, and formating output the number with 2 decimal point. About which high-low word order corresponding to which value, please refer to the Address Operation Table.

function highLowByteSwitch(floatNumber)
    addr_setfloat("@W_0#HDW23036",floatNumber,0,2)
   local newFloat = addr_getfloat("@W_0#HDW23036")
   local formattedFloat = string.format("%.2f",newFloat)
   print("The formatted float value is the : "..formattedFloat)
   return formattedFloat
end

1.10 Read 64bits Unsigned Value

In our built-in function library doesn't have the function for reading 64-bit unsigned format value, so the following function is for solve this. But if the number is greater 2^53, the precision will be lost. So the final result will be a little bit different from the original value.

function addr_getquatra(address)
   local highAddress = addr_newnoaddr(address,2)
   local low32 = addr_getdword(address)
   local high32 = addr_getdword(highAddress)
   --print("the low number is "..low32)
   --print("the high number is "..high32)
   local formatVal = string.format("%64.0f",2^32*high32+low32)
   print("the format value is ".. formatVal)
   return formatVal
end

2 Third part server

V-Box have two mode.One is for V-Net,User need to use WECON server to store data.We call this V-NET platform.

1.Europe server:eu.v-box.net 

2.Asean server:asean.v-box.net

Second is for OpenCloud mode.It means V-Box data will transfer to third part server and do not want to store data to WECON server.We call OpenCloud paltform

OpenCloud platform is used in configuring the script.Then V-Box can connect with third part server.

Both mode can support script  to connect with third part server.the difference:

1.If you want to store in WECON server ,please use V-NET.

2.If your server requires SSL certificate to log in,please use OpenCloud.Because only OpenCloud platform can support to upload certificate

Information

✎Note: Before program the script of MQTT, please make sure the server(MQTT broker) can be connected through MQTT Client tool.

Tool link: MQTT.fx

2.1 Test server(General Example)

The following example is trying to publish to the topic "testtopic/test/no1/7890", and subscribe the topic "testtopic/test/no1/123456". 

And the JSON message is like follows:

{
"timestamp": 1631152760,
"messageId": 1,
"event": "test_data",
"mfrs": "HMI/box",
"data":
  {
  "id" : 1436217747670454274,
  "waterlevel" : 48,
  "temperture" : 23
  }
}
--MQTT configuration table
local MQTT_CFG={}
--if there is no need the username and password, please put them as ""
MQTT_CFG.username = "weconsupport"
MQTT_CFG.password = "123456"
MQTT_CFG.netway = 0
MQTT_CFG.keepalive = 60
MQTT_CFG.cleansession = 1
--TCP URL
MQTT_URL = "tcp://mq.tongxinmao.com:1883"
--Client ID
MQTT_CLIENT_ID = "V-BOXH-AG"

--Generate UUID
function uuid()
   local seed = {'e','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
   local tb = {}
   for i=1, 32 do
       table.insert(tb, seed[math.random(1,16)])
   end
   local sid=table.concat(tb)
   return string.format('%s',
       string.sub(sid,1,32)
    )
end


--Topic name to subscribed
local SUBSCRIBE_TOPIC = 'testtopic/test/no1/123456'

--Topic name to be published 
local PUBLISH_TOPIC = 'testtopic/test/no1/7890'


--real time
local LAST_TIME = 0


--initialize mqtt
function mqtt_init()
   print(string.format("mqtt init mqtt_url:%s mqtt_clientid:%s", MQTT_URL, MQTT_CLIENT_ID))
   if g_mq then
        mqtt.close(g_mq) --Close mqtt object
   end
    g_mq, err = mqtt.create(MQTT_URL, MQTT_CLIENT_ID) -- create mqtt object,and declare it as a global variable
   if g_mq then
        g_mq:on("message", mqtt_msg_callback) -- Register a callback for receiving messages
        g_mq:on("offline", mqtt_msg_offline)  -- Register a callback for offline
       print("mqtt init success")
   else
       print("mqtt init failed:", err)
   end
end

-- connect to mqtt
function mqtt_connect()
   print("mqtt connecting...")
   local stat, err = g_mq:connect(MQTT_CFG)
   if stat == nil then
       print("mqtt connect failed:", err)
       return
   else
       print("mqtt connected")
   end
    g_mq:subscribe(SUBSCRIBE_TOPIC, 0)
end

--Offline callback function
function mqtt_msg_offline(cause)
   print("mqtt offline, cause:", cause)
end

-- Received message callback function
function mqtt_msg_callback(topic, msg)
   print("topic:", topic)
   print("msg:", msg)
   local objMsg = json.decode(msg)
   local water = objMsg.data.waterlevel
   local temp = objMsg.data.temperature
    addr_setword("@HDW20",water)
    addr_setword("@HDW10",temp)
end

--Send data (data upload to platform and encapsulate it with custom functions)
function send_data()
   local pub_data = {
        timestamp = os.time(),
        messageId = 1,
        event = 'test_data',
        mfrs = 'V-Box',
        data = {
            id = uuid(),
            waterlevel = addr_getword("@HDW10"),
            temperature = addr_getword("@HDW20")
        }
    }
   return g_mq:publish(PUBLISH_TOPIC, json.encode(pub_data), 0, 0)
end


--main function fixed timed execution
function MQTT.main()
   --dosomething
   print(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " main start")
   --determine the mqtt object whether exist
   if g_mq then
       --determine the mqtt object whether has been connected or not
       if g_mq:isconnected() then
            send_data()
       else
           --if exceed 5 sec not connect, reconnect once
           if os.time() - LAST_TIME > 5 then
                LAST_TIME = os.time()
               --reinitial the mqtt object
                mqtt_init()
               --connect to mqtt or reconnect
                mqtt_connect()
           end
       end
   else
       --mqtt object does not exist so create new one
        mqtt_init()
   end
   print(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " main end")
end

2.2 Customer server:grouprobotinfo.com

This demo does not use SSL certification. Script is as below

Demo1:

-- Meta class
--main
function mq.main()
if not mq.m then
 local err = ""

  mq.m, err = mqtt.create("tcp://grouprobotinfo.com:1883", "ClienID")  -- create connection
 if mq.m then
   mq.config = {
    username = "",-- ID
    password = "",-- password
    netway = 1, -- Ethernet connection, WIFI=1
   -- keepalive = 100, -- Optional, set the connection heartbeat interval for 100 seconds.
   -- cleansession = 0, -- Optional, keep session
   }
   mq.m:on("message", function(topic, msg) -- Register for receiving message callbacks
   local str = string.format("%s:%s", topic, msg)
   -- print("mqtt msg:", str) -- Print out the received topics and content
  end)
   mq.m:on("offline", function (cause) -- Register for lost connection callbacks
   -- addr_setstring("@xxx", "cause"..(cause or " got nil"))
  end)
   mq.m:on("arrived", function() -- Registration for sending messages to callbacks 
   print("msg arrived")
  end)
 else
  print("mqtt create failed:", err) -- Create object failed
 end
else
 if mq.m:isconnected() then -- If online, post a message
    local phaseStatus ="unknow"
    if addr_getbit("@Standby")== 1 then
      phaseStatus = "Standby"
    elseif addr_getbit("@Pre-Freeze")==1 then
      phaseStatus= "Pre-Freeze"
    elseif addr_getbit("@Prepare")==1 then
      phaseStatus ="Prepare"
    elseif addr_getbit("@Primary Dry")==1 then
      phaseStatus = "Primary dry"
    elseif addr_getbit("@Secondary Dry")==1 then
      phaseStatus = "Secondary Dry"
    end
    --print(addr_getbit("@Primary Dry"))
-------------------------------------------------------------------------------------------------------------------------
    local activating ="unknow"
    if addr_getbit("@Compressor")==1 then
      activating = ",".."Compressor"
    end
    if addr_getbit("@Silicone Pump")==1 then
      activating = activating..",".."Silicone Pump"
    end
    if addr_getbit("@Vacuum Pump")==1 then
      activating = activating..",".."Vacuum Pump"
    end
    if addr_getbit("@Root Pump")==1 then
      activating = activating..",".."Root Pump"
    end
    if addr_getbit("@Heater")==1 then
      activating = activating..",".."Heater"
    end
    if addr_getbit("@Valve Silicone")==1 then
      activating = activating..",".."Valve Silicone"
    end
    if addr_getbit("@Valve Ice Condenser")==1 then
      activating = activating..",".."Valve Ice Condenser"
    end
    if addr_getbit("@Valve Vacuum Pump")==1 then
      activating = activating..",".."Valve Vacuum Pump"
    end
    local pr_activating =string.sub(activating,2)
   --  print(pr_activating)  
    local status_text ="unknow"
    if addr_getbit("@Status Run")==1 then
      status_text = "RUNNING"
    else
      status_text = "STOP"
    end
-------------------------------------------------------------------------------------------------------------------------  
    local js = {type="status",
        mc_name ="FD300",
        status=status_text,
        elapsed_time={
          hour=addr_getword("@Elapsed Time (Hour)"),
          min=addr_getword("@Elapsed Time (Minute)"),
          sec=addr_getword("@Elapsed Time (Second)")
        },
        phase = phaseStatus,
        step = addr_getword("@Step"),
        activating_output = pr_activating,
        sv=addr_getshort("@SV Silicone")/10,
        pv=addr_getshort("@PV Silicone")/10,
        product1=addr_getshort("@Product 1")/10,

        product2=addr_getshort("@Product 2")/10,
        product3=addr_getshort("@Product 3")/10,
        product4=addr_getshort("@Product 4")/10,
        ice1=addr_getshort("@Ice condenser 1")/10,
        ice2=addr_getshort("@Ice condenser 2")/10,
        vacuum=addr_getfloat("@Vacuum")
     }
    local jsAlarm = {  HPC = addr_getbit("@B_25395#W0.00"),
          ODPC = addr_getbit("@B_25395#W0.01"),
          MTPC=addr_getbit("@B_25395#W0.02"),
          HTT = addr_getbit("@B_25395#W1.03"),
          CPC = addr_getbit("@B_25395#W0.08"),
          CPSP =addr_getbit("@B_25395#W1.00"),
          CPVP =addr_getbit("@B_25395#W0.10"),
          CPRP =addr_getbit("@B_25395#W0.11"),
          HP =addr_getbit("@B_25395#W1.01"),
          PP= addr_getbit("@B_25395#W1.02"),
          PO=addr_getbit("@B_25395#W0.07"),
          FSE=addr_getbit("@B_25395#W2.04"),
          AVVSVV=addr_getbit("@B_25395#W1.12"),
          ICHT=addr_getbit("@B_25395#W3.06")
     }
    -- ("@B_25395#CIO1.02")
     mq.m:publish("mqtt-v-box-epsilon-fd300", json.encode(js) , 0, 0)
     mq.m:publish("mqtt-v-box-epsilon-alarm-fd300", json.encode(jsAlarm) , 0, 0)
 else
  local stat, err = mq.m:connect(mq.config) -- connection
  if stat == nil then --Determine whether to connect
   print("mqtt connect failed:", err)
   return -- Connection failed, return directly
  end
   mq.m:subscribe("mqtt-v-box-epsilon", 0)-- Subscribe to topics

 end
 -- mq.m:unsubscribe("stc/test")
 -- mq.m:disconnect() -- close matt
 -- mq.m:close() -- close clase
end
end

2.3 Azure platform

In this demo,V-Box connects with Azure by SSL certification.

Video link: https://youtu.be/cdI6rIQcpMY?list=PL_Bpnb2RgaksCic9HCcVAZhU9sYwCRKzW

Tool Download link: https://wecon-disk.oss-ap-southeast-1.aliyuncs.com/Download/WIKI/V-BOX/Demo/Azure/Azure%20tool.zip

Script is as below

--https://support.huaweicloud.com/qs-IoT/iot_05_0005.html  mqtt.fx monitor to connect azure iot
sprint = print

--Get custom configuration parameters (vbox custom information)
--local CUSTOM = bns_get_config("bind")
--local DS_ID = CUSTOM.DSID or "60a71ccbbbe12002c08f3a1a_WECON"



--Cloud mode interface to obtain the MQTT information configured by the cloud platform: (5 returns, namely the server address, client ID, connection table, last word table, certificate table)
local MQTT_URL, MQTT_CLIENTID, MQTT_CFG, MQTT_LWT, MQTT_CART = mqtt.setup_cfg()

--MQTT_CFG.username = '60a71ccbbbe12002c08f3a1a_WECON'
--MQTT_CFG.password='wecon123'
--MQTT_CLIENTID = '60a71ccbbbe12002c08f3a1a_WECON_0_0_2021052110usernxame:60a71ccbbbe12002c08f3a1a_WECONpassword:a0a951581855aa8e0262129da6cf1b43f2c0ecfac4fa56117fc5a20c90be169a'

--publish to topics
local pub_RE_TOPIC = string.format('devices/wecon_02/messages/events/')
--Subscribe topics
local Subscribe_RE_TOPIC1 = string.format('devices/wecon_02/messages/devicebound/#')

--variable
local last_time = 0



--Timing main function
function Azure.main()

   sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " Azureiot.main start")
   if g_mq then
        if g_mq:isconnected() then
            send_Data()
        else
            if os.time() - last_time > 20 then
                last_time = os.time()
                mymqtt_connect()
            end
        end
    else
        mymqtt_init()
    end
    sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " Azureiot.main end")
end

-- Initialize MQTT
function mymqtt_init()
    sprint(string.format("mqtt init mqtt_url:%s mqtt_clientid:%s", MQTT_URL, MQTT_CLIENTID))
    g_mq, err = mqtt.create(MQTT_URL, MQTT_CLIENTID) -- Create the object and declare it as a global variable
    if g_mq then
        g_mq:on("message", mymqtt_msg_callback) -- Register to receive message callbacks
        sprint("mqtt init success")
    else
        sprint("mqtt init failed:", err)
    end
end

-- Connect to MQTT server
function mymqtt_connect()
    sprint("mqtt connecting...")
    local stat, err = g_mq:connect(MQTT_CFG,MQTT_LWT, MQTT_CART)
    if stat == nil then
        sprint("mqtt connect failed:", err)
        return
    else
        sprint("mqtt connected")
    end
    g_mq:subscribe(Subscribe_RE_TOPIC1, 0) 
end

-- Receive MQTT message callback function
function mymqtt_msg_callback(topic, msg)
    print("topic:",topic)
    print("revdata:",msg)
   -- local revData = json.decode(msg)
 --  if topic == Subscribe_RE_TOPIC1 then --Process topic information subscribed from the cloud
-- if string.match(topic,Subscribe_RE_TOPIC1) then
     --   print("topi11:",topic)
       setValue(revData)
   -- end
end

--Process the received data
--function setValue(revData)
   -- if revData ~=nil then 
 --       for i,v in pairs(revData) do
  --          print("Data received:",i,v)
  --      end
   -- end
--end

--Get real-time data
function getData()
    local jdata = {}
    local addr = bns_get_alldata()
    print(json.encode(addr))
    for i,v in pairs(addr) do
        if v[2] == 1 then
           jdata[v[3]] = v[4]
        end
    end
    return jdata
end 



--send data
function send_Data()
    local pub_data = {100
     --   services={{

            --serviceId ='Temperature',
           -- properties={
               -- value = 55
           -- },
       -- }}
}
sprint(json.encode(pub_data))
print("..........",pub_RE_TOPIC)
    return g_mq:publish(pub_RE_TOPIC, json.encode(pub_data), 0, 0)
end

2.4 Huawei platform

Information

✎Note:Huawei IOT DA function is only in China area.If you want this function,you need to use chinese mobile to register

1.Register a account: https://www.huaweicloud.com/intl/en-us/s/JUlPVERNJQ

2.log in the Huawei IOTDA

https://console.huaweicloud.com/iotdm/?region=cn-north-4&locale=en-us#/dm-portal/home

3.Create product

1624433478954-859.png

4.Product name,manufacturer,device type and industry,set according to your own needs.

Protocol: MQTT

Data Type: JSON

After finishing configuration,please click "OK"

1624433531968-337.png

5.Device

After product register,continue to configure "individual register".Click "Device"-->"individual register"

1624434757597-117.png

Notes for registering device:

Product: Previous product registration.

Node ID, Device Name: set according to your own needs.

Secret: need to be configured, will be used when connecting later

After configuration, click OK to generate a device ID and password, which will be used for device access later.

1624436421499-613.png

1624437798012-126.png

6. Connection authentication (use MQTT.fx tool to access the IoT platform)

(1)Open mqttClientIdGenerator tool Java(TM) Platform SE binary

Download

1624437573798-815.png

(2)Fill in the device ID and secret (deviceid and secret generated when registering the device) to generate connection message

Client ID, user name, password

1624437756866-251.png

(3) Download certificate file"North-Beijing4"

https://support.huaweicloud.com/en-us/devg-iothub/iot_02_1004.html

1624438225398-363.png

1624438260025-610.png

7.Run MQTTfx tool to connect with Huawei

Download link: http://mqttfx.jensd.de/index.php/download

(1)Click on the setting ICON

1624438821280-974.png

(2)Fill in IIOT MQTT device access address, and configure authentication parameters.
First: It is the server and port connected to Huawei IOT, which can be viewed through the overview of the interface.

1624439086268-985.png

Domain name:iot-mqtts.cn-north-4.myhuaweicloud.com

Port: 8883

Client ID: check step 6

1624439672168-492.png

(3)Upload SSL certificate file,check step 6

Select folder java-->DigiCertGlobalRootCA.crt.pem and click OK or apply button

1624439912938-659.png

(4)Connect and test publish and subscribe

1624440014872-688.png

1624440026937-386.png

Huawei publish topic format: $oc/devices/{device_id}/sys/properties/report

1624440404119-815.png

Huawei subscribe topic format: $oc/devices/{device_id}/sys/commands/#

1624447157493-672.png

1624447209982-715.png

(5).How to configure to view the received data format intuitively, multiple products (Huawei) are required to configure the model. The specific steps are as follows:
①Select the corresponding product from Huawei products to view

1624440647663-632.png

②Custom model: used to display the service ID name of the configuration report.

1624440793982-974.png

1624440883015-105.png

③Add property, ID of monitoring point, and data format:

1624441052296-108.png

④After the configuration is complete, check the received data on the device

1624441186851-536.png

Huawei by SSL certification.

1.Create a project access for Huawei IOT

2.configure MQTT configuration

1624506363847-661.png

3.Create a script with the demo as below.

 Script is as below

-- mqtt.fx simulated access to Huawei Cloud IoT platform refer to 2.4
sprint = print

--Get custom configuration parameters (gateway customization information)
local CUSTOM = bns_get_config("bind")
local DS_ID = CUSTOM.DSID or "5dfa0700df1ae506179afb9c_wecon"

--OpenCloud mode interface, obtain MQTT information configured on cloud platform: (5 returned, respectively server address, client ID, connection table, last word table, certificate table)
local MQTT_URL, MQTT_CLIENTID, MQTT_CFG, MQTT_LWT, MQTT_CART = mqtt.setup_cfg()

MQTT_CFG.username =DS_ID
MQTT_CFG.password='d030d92338fcc18cd10fabb3003a4a0f6620fa6822cd3c23b1d9bc790200c6e7'
MQTT_CLIENTID = '5dfa0700df1ae506179afb9c_wecon_0_0_2019121819'

--publish topic format:$oc/devices/{device id}/sys/properties/report

local pub_RE_TOPIC = string.format('$oc/devices/60a71ccbbbe12002c08f3a1a_WECON/sys/properties/report')

--variate
local last_time = 0

--Timing principal function
function hwyiot.main()

   sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " hwyiot.main start")
   if g_mq then
        if g_mq:isconnected() then
            send_Data()
        else
            if os.time() - last_time > 20 then
                last_time = os.time()
                mymqtt_connect()
            end
        end
    else
        mymqtt_init()
    end
    sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " hwyiot.main end")
end

--  initializationMQTT
function mymqtt_init()
    sprint(string.format("mqtt init mqtt_url:%s mqtt_clientid:%s", MQTT_URL, MQTT_CLIENTID))
    g_mq, err = mqtt.create(MQTT_URL, MQTT_CLIENTID) -- Create the object and declare it as a global variable
    if g_mq then
        g_mq:on("message", mymqtt_msg_callback) -- Register to receive message callbacks
        sprint("mqtt init success")
    else
        sprint("mqtt init failed:", err)
    end
end

-- Connect to the MQTT server
function mymqtt_connect()
    sprint("mqtt connecting...")
    local stat, err = g_mq:connect(MQTT_CFG,MQTT_LWT, MQTT_CART)
    if stat == nil then
        sprint("mqtt connect failed:", err)
        return
    else
        sprint("mqtt connected")
    end

 --subscribe topic format:$oc/devices/{device_id}/sys/commands/#

  g_mq:subscribe('$oc/devices/60a71ccbbbe12002c08f3a1a_WECON/sys/commands/#', 0) 
end

-- Receive the message callback function
function mymqtt_msg_callback(topic, msg)
    sprint("recv data!")
    sprint("topic:msg", topic,msg)
    print(msg)
    local revData = json.decode(msg)

end

--Send data
function send_Data()
    local pub_data = {
        msgType = 'deviceReq',
        data = {{
            serviceId ='Battery',
            serviceData={
                batteryLevel = 55
            }
        }}
    }
    return g_mq:publish(pub_RE_TOPIC, json.encode(pub_data), 0, 0)
end

4.Download project access into V-Box to test in debug page 

1624506710354-406.png

1624506666650-161.png

2.6 AWS platform

Log in AWS

Login aws account and click“Connect an IoT device”

image-20220709165402-1.png

image-20220709165402-2.png

Create policy

Click “Secure”--->“Policies”--->“Create policy”--->Click “Create”

image-20220709165402-3.png

Name the policy--->Click “JSON”--->Copy the following content--->Click “Create”

image-20220709165402-5.png

image-20220709165402-4.png

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect",
        "iot:Publish",
        "iot:Subscribe",
        "iot:Receive",
        "greengrass:Discover"
      ],
      "Resource": "*"
    }
  ]
}

Create things

Click “Manage”--->“Things”--->“Create things”--->“Create single thing”

image-20220709165402-6.png

image-20220709165402-7.png

Name the thing--->Click “Next”

image-20220709165402-8.png

Select the way to create certificate

image-20220709165402-9.png

Select policy

image-20220709165402-10.png

image-20220709165402-11.png

MQTT.fx tool

Click “View Setting” to get the “Broker Adress”

image-20220709165402-13.png

image-20220709165402-12.png

Create one connection in MQTT.fx tool, set broker port as 8883.

image-20220709165402-14.png

Upload the CA File, Client Certificate File, Client Key File

image-20220709165402-15.png

Publish message to topic “TEST”

image-20220709165402-17.png

Click”Test”--->”MQTT test client”--->”Subscrible to a topic”, to get message publish from MQTT.fx tool.

image-20220709173500-1.png

And we can also send message form AWS platform to MQTT.fx tool.

image-20220709165402-18.png

CloudTool

Copy the same setting in MQTT.fx to MQTT configuration

image-20220709165402-19.png

 Add a lua script and copy the lua demo into it.

image-20220709165402-20.png

Information

✎Note: Before using the following demo script, please make sure the V-Box firmware is newer than 22110701

sprint = print

--Cloud mode interface to obtain the MQTT information configured by the cloud platform: (5 returns, namely the server address, client ID, connection table, last word table, certificate table)

local MQTT_URL, MQTT_CLIENTID, MQTT_CFG, MQTT_LWT, MQTT_CART = mqtt.setup_cfg()

--publish to topics

local pub_RE_TOPIC = string.format('TEST')

--Subscribe topics

local Subscribe_RE_TOPIC1 = string.format('TEST')

--variable

local last_time = 0

--Timing main function

function aws.main()

            sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " aws.main start")

           if g_mq then

               if g_mq:isconnected() then

                    send_Data()

               else

               if os.time() - last_time > 5 then

                    last_time = os.time()

                    mymqtt_connect()

               end

           end

           else

                mymqtt_init()

           end

            sprint(os.date("%Y-%m-%d %H:%M %S", os.time()) .. " aws.main end")

end



-- Initialize MQTT

function mymqtt_init()

                sprint(string.format("mqtt init mqtt_url:%s mqtt_clientid:%s", MQTT_URL, MQTT_CLIENTID))

                g_mq, err = mqtt.create(MQTT_URL, MQTT_CLIENTID, 1) -- Create the object and declare it as a global variable, 1 means using the domain to connect

               if g_mq then

                    g_mq:on("message", mymqtt_msg_callback) -- Register to receive message callbacks

                    sprint("mqtt init success")

               else

                    sprint("mqtt init failed:", err)

               end

end

-- Connect to MQTT server

function mymqtt_connect()

                sprint("mqtt connecting...")

               local stat, err = g_mq:connect(MQTT_CFG,MQTT_LWT, MQTT_CART)

               if stat == nil then

                    sprint("mqtt connect failed:", err)

                   return

               else

                    sprint("mqtt connected")

               end

                g_mq:subscribe(Subscribe_RE_TOPIC1, 0)

end

-- Receive MQTT message callback function

function mymqtt_msg_callback(topic, msg)

               print("topic:",topic)

               print("revdata:",msg)

               local revData = json.decode(msg)

               print (revData)

               if topic == Subscribe_RE_TOPIC1 then --Process topic information subscribed from the cloud

                   if string.match(topic,Subscribe_RE_TOPIC1) then

                       --if revData ~= nil then

                       for k,v in pairs (revData) do

                           print("printing revdata after kv here")

                           print (k,v)

                       end

                   print ("current state is",fanstate)

                       --end

                   end

               end

end



--Get real-time data

function getData()

               local jdata = {}

               local addr = bns_get_alldata()

               print(json.encode(addr))

               for i,v in pairs(addr) do

                   if v[2] == 1 then

                        jdata[v[3]] = v[4]

                   end

               end

               return jdata

end

--send data

function send_Data()

               local pub_data =
                {
                   123
                }

sprint(json.encode(pub_data))

print("..........",pub_RE_TOPIC)

               return g_mq:publish(pub_RE_TOPIC, json.encode(pub_data), 0, 0)

end

Get message in AWS

image-20220709165402-21.png

2.7 Mysql

In this demo you can use Mysql import the data to the terminal device through the V-box or save the data to the any Mysql database by the V-box.

1.Install Mysql

version

Mysql的软件版本.png

2.Install Navicat

version

navicat 版本.png

Connecting to Mysql with navicat.

连接到mysql.png

3.Create database

Character set should be choose utf8mb3/utf8mb4 and Collation choose utf8mb3_danish_ci/utf8mb4_danish_ci.

创建数据库.png

4.Create data table

Create a table, enter the fields you need.

创建表1.png

Save, enter table name.

创建表2.png

5.Input Table Data

输入或者导入数据.png

6.Script

luaMySql.init(string sourcename, string username, string password, string host, number port, string character)

Function: Configure database connection parameters

Parameter:

sourcename: the name of database

username: the username of the connection

password: the password of the connection

host: the host name of the connection

port: the host port of the connection

character: the character set of the connection

Return:

Succeed: string

Failed: multi

luaMySql.exec(string statement)

Function: Execute the given SQL statement without returning the result set (add, delete, change)

Parameter:

statement: the given SQL statement

Return:

Succeed: status: returns the number of rows affected by SQL statement execution.

Failed: nil, errorString

luaMySql.execWithResult(string statement)

Function: Execute the given SQL statement returning the result set (check)

Parameter:

statement: the given SQL statement

Return:

Succeed: table: returns the result set

Failed: nil, errorString

For example:

-- Assuming the "mysqlclient" library is properly installed and available
mysql = require("mysqlclient")

function DataInitRight()
   local dbName = "excel"
   local user = "root"
   local pwd = "XXXXX"
   local host = "192.168.39.146"
   local port = 3306
   local character = "utf8mb3"
   
    mysql.init(dbName, user, pwd, host, port, character)
end

function ExecFunc()
    status, errorString = mysql.exec("delete from student where Name = 'XXX';")  --Delete statement, column name = table element
   if nil == status then
       print("ExecFunc() error:", errorString)
       return -1
   else
       print("the number of rows affected by the command:", status)
   end
       return 0
end


function ExecWithResultFunc()
    status, errorString = mysql.execWithResult("select * from student;")
   if nil == status then
       print("ExecWithResultFunc() error:", errorString)
       return -1
   else
       print("ExecWithResultFunc() success : status type = ", type(status))
       print("ExecWithResultFunc() success : status len = ", #status)
       local num = #status
       local i = 1
       if num > 0 then
           for i = 1, num, 1 do
               local var = string.format("select result[%d] :Num = %d,Name = %s,Age = %d", i, status[i].Num, status[i].Name,status[i].Age)   --Iterate through the data in the table, noting whether the elements are strings or numbers        
               print(var)
           end
       end
       print("---------------")
   end
   return 0
end

function MySQL.main()
   print("script running ...")
    DataInitRight()

   -- use exec demo
   if ExecFunc() < 0 then
       return
   end

   -- use execWithResult demo
   if ExecWithResultFunc() < 0 then
       return
   end

   print("script running success")
end

7.Debug

调试结果.png

8.Problem

During our debugging process it may there are some problems about Mysql, such as

  • MySQL: Host  192.168.XXX.XXX  is not allowed to connect.
  • MySQL: Host  192.168.XXX.XXX  is blocked because of many connection errors.
  • MySQL: SSL connection error: unknown error number.
  • 1449-The user specified as a definer(‘mysql.infoschema‘@localhost‘) does not exist.

This type of problem has nothing to do with scripts or devices, it is a Mysql configuration issue. If you have any of these problems, please look for a solution online.

Information

✎Note: If you want to use CMD to access Mysql, you need to add the bin file to the environment variable, please check online for details of the operation.