local sys = require "sys" local internal_api = require "internal_api" local cjson = require "cjson" local sensor_monitor = require "application.sensor_monitor" local bit = require "bit" local mqtt_client = require "application.mqtt_client" local est = require "application.est" local schedule = require "storage.schedule" local event = require "main.event" local sensors = require "application.sensors" require "main.global" local configuration = require "storage.configuration" local devices = require "main.devices" local protocol = {} local warnings = {} local isAuto = false local isSetWarn = false local function length(t) local res = 0 for k, v in pairs(t) do res = res + 1 end return res end local function sendAck(sn, identifier, data) mqtt_client.send("ipc/" .. GW_SN .. "/" .. APP_KEY .. "/device/" .. sn .. "/data_filtered/service/" .. identifier, cjson.encode(data)) end local function control_switch(data) local lt = data.lt local value = data.value local do_new = 0 if LIGHT_TYPE == 0 then -- 接触器 est.contactor_control(lt, value) else -- 多路开关控制器 est.multi_control(lt, value) end local result = true --local result = sys.waitUntil(SET_DO_ACK, 2000) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = result and 0 or 1 sendAck(data.sn, data.identifier, ack) end local function get_state(data, isGet, tags) local node_sn = {"MultiSwitch1", "MultiSwitch2", "MultiSwitch3", "MultiSwitch4", "MultiSwitch5", "MultiSwitch6", "MultiSwitch7", "MultiSwitch8", "MultiSwitch9", "MultiSwitch10"} -- 多路开关控制器sn local sensor_status = sensor_monitor.get_status() sensors.get_do_status() -- 接触器控制 sensors.get_fan_speed() for i = 1, MULTI_CONT, 1 do -- 多路开关控制器控制 sensors.get_multi_do_feedback(node_sn[i]) end for i = 1, MULTI_CONT, 1 do sensors.get_multi_do_current(node_sn[i]) end local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} if tags and isGet then -- 电压、总电流 变化上报(数据波动超过阈值),DO、DI、MSDO、MSDI 任意一个变化引起上报 for k, v in pairs(tags) do --[[if k ~= "DO" then ack.tags[k] = v else ack.tags[k] = "" for i = 1, 8, 1 do ack.tags[k] = ack.tags[k] .. (bit.band(sensor_status.ADIO.tags.DO or 0, bit.lshift(1, i - 1)) == 0 and 0 or 1) end end]] if k == "DO" or k == "MSDO" or k == "MSDI" then if k == "DO" then ack.tags[k] = "" for i = 1, 8, 1 do ack.tags[k] = ack.tags[k] .. (bit.band(sensor_status.ADIO.tags.DO or 0, bit.lshift(1, i - 1)) == 0 and 0 or 1) end elseif k == "MSDO" then if length(sensor_status.MultiSwitch.tags.MSDO) >= 1 then ack.tags.MSDO = "" local muti_DO for j = 1, MULTI_CONT, 1 do muti_DO = "" if sensor_status.MultiSwitch.tags.MSDO[j] then for i = 1, 6, 1 do muti_DO = muti_DO .. (bit.band(bit.rshift(sensor_status.MultiSwitch.tags.MSDO[j], i-1), 0x01) == 0 and 0 or 1) end -- log_print.info(string.format("upload muti %d MSDO %s", j, muti_DO)) end ack.tags.MSDO = ack.tags.MSDO .. muti_DO .. "#" end ack.tags.MSDO = string.sub(ack.tags.MSDO, 1, -2) end elseif k == "MSDI" then if length(sensor_status.MultiSwitch.tags.MSDI) >= 1 then ack.tags.MSDI = "" local muti_DI for j = 1, MULTI_CONT, 1 do muti_DI = "" if sensor_status.MultiSwitch.tags.MSDI[j] then for i = 1, 6, 1 do muti_DI = muti_DI .. (bit.band(bit.rshift(sensor_status.MultiSwitch.tags.MSDI[j], i-1), 0x01) == 0 and 0 or 1) end -- log_print.info(string.format("upload muti %d MSDI %s", j, muti_DI)) end ack.tags.MSDI = ack.tags.MSDI .. muti_DI .. "#" end ack.tags.MSDI = string.sub(ack.tags.MSDI, 1, -2) end end else ack.tags[k] = v end end else -- 召测控制器状态(所有状态数据)/定时上报 local i = 1 while (sensor_monitor.get_sensorUpdate() and i <= 4) do i = i + 1 sys.wait(1000) if i == 4 then return end end -- 温湿度 for k, v in pairs(sensor_status.TempHumi.tags) do ack.tags[k] = v end -- ADIO if #sensor_status.ADIO.tags.DI >= 1 then ack.tags.DI = sensor_status.ADIO.tags.DI end if sensor_status.ADIO.tags.DO ~= nil then ack.tags.DO = "" for i = 1, 8, 1 do ack.tags.DO = ack.tags.DO .. (bit.band(sensor_status.ADIO.tags.DO, bit.lshift(1, i - 1)) == 0 and 0 or 1) end end if sensor_status.ADIO.tags.fan1 ~= nil and sensor_status.ADIO.tags.fan2 ~= nil then ack.tags.fan1 = sensor_status.ADIO.tags.fan1 ack.tags.fan2 = sensor_status.ADIO.tags.fan2 end -- 智能门锁 for k, v in pairs(sensor_status.SmartLock.tags) do ack.tags[k] = v end -- 电表 for k, v in pairs(sensor_status.PowerMeter.tags) do ack.tags[k] = v end --[[ for k, v in pairs(sensor_status.PowerSwitch.tags) do ack.tags[k] = v end ]] -- 多路开关控制器 if length(sensor_status.MultiSwitch.tags.MSDO) >= 1 then ack.tags.MSDO = "" local muti_DO for j = 1, MULTI_CONT, 1 do muti_DO = "" if sensor_status.MultiSwitch.tags.MSDO[j] then for i = 1, 6, 1 do muti_DO = muti_DO .. (bit.band(bit.rshift(sensor_status.MultiSwitch.tags.MSDO[j], i-1), 0x01) == 0 and 0 or 1) end -- log_print.info(string.format("upload muti %d MSDO %s", j, muti_DO)) end ack.tags.MSDO = ack.tags.MSDO .. muti_DO .. "#" end ack.tags.MSDO = string.sub(ack.tags.MSDO, 1, -2) end if length(sensor_status.MultiSwitch.tags.MSDI) >= 1 then ack.tags.MSDI = "" local muti_DI for j = 1, MULTI_CONT, 1 do muti_DI = "" if sensor_status.MultiSwitch.tags.MSDI[j] then for i = 1, 6, 1 do muti_DI = muti_DI .. (bit.band(bit.rshift(sensor_status.MultiSwitch.tags.MSDI[j], i-1), 0x01) == 0 and 0 or 1) end -- log_print.info(string.format("upload muti %d MSDI %s", j, muti_DI)) end ack.tags.MSDI = ack.tags.MSDI .. muti_DI .. "#" end ack.tags.MSDI = string.sub(ack.tags.MSDI, 1, -2) end -- 安全用电模块 for k, v in pairs(sensor_status.SafeElectricity.tags) do ack.tags[k] = v end end if tags and isGet then -- 电压、总电流 变化上报(数据波动超过阈值),DO、DI、MSDO、MSDI 任意一个变化引起上报 log_print.info("电压、电流 数据波动超过阈值、DI/DO变化上报...") mqtt_client.send("ipc/" .. GW_SN .. "/" .. APP_KEY .. "/device/" .. data.sn .. "/data_filtered/event/" .. data.identifier, cjson.encode(ack)) else if isGet then log_print.info("控制器状态定时上报...") sendAck(data.sn, data.identifier, ack) else log_print.info("召测控制器状态上报...") sendAck(data.sn, data.identifier, ack) end end sensor_monitor.update_status() end local function set_schedule(data) local monthDate = data.date -- MMDD local chn = data.lt -- 回路序号 local sche = data.strategy -- 策略 local mode = data.mode local daySche = string.split(sche, "#") local result if mode == 0 then local month = tonumber(string.sub(monthDate, 1, 2)) local date = tonumber(string.sub(monthDate, 3, 4)) result = schedule.set_absolutely(month, date, daySche, chn) elseif mode == 1 then local time = os.date("*t", os.time()) schedule.set_repeat(time.month, time.day, daySche, chn, tonumber(monthDate)) end if LIGHT_TYPE == 0 then Strategy_chn[chn] = true -- 接触器控制更新策略 elseif LIGHT_TYPE == 1 then Strategy_chn[chn] = true -- 多路开关控制器控制更新策略 end local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = result and 0 or 1 sendAck(data.sn, data.identifier, ack) end local function get_schedule(data) local chn = data.lt -- 要查询策略的回路号 local monthDate = data.date local num = data.count local month = tonumber(string.sub(monthDate, 1, 2)) local date = tonumber(string.sub(monthDate, 3, 4)) local dayIndex = schedule.toDayIndex(month, date) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.lt = chn ack.tags.date = monthDate ack.tags.errorCode = 0 ack.tags.strategy = "" for i = 1, num, 1 do local m, d = schedule.fromDayIndex(dayIndex) dayIndex = dayIndex + 1 if dayIndex > 366 then dayIndex = 1 end local sche = schedule.readDay(m, d) ack.tags.strategy = ack.tags.strategy .. (sche and sche[tostring(chn)] or "") .. (i ~= num and "#" or "") -- 以#间隔相邻日期,当某一日为空值时,返回空值,例如:##表示该日期无策略 end sendAck(data.sn, data.identifier, ack) end local function set_config(data) --log_print.info(cjson.encode(data)) for k, v in pairs(SdbConfig) do if k == "LockDelay" and data[k] and SdbConfig[k] ~= data[k] then -- 智能锁闭锁延时参数 sensors.set_lock_delay(data[k]) end if k == "LightType" and data[k] and SdbConfig[k] ~= data[k] then -- 照明类型 LIGHT_TYPE = data[k] if LIGHT_TYPE == 0 then TOTAL_CH = 8 -- 接触器控制--8通道 est.contactor_init() else TOTAL_CH = MULTI_CONT * 6 -- 多路开关控制器控制--最多支持60通道(下挂10个多路开关控制器) est.multi_init() end end if k == "FanTmp" and data[k] and SdbConfig[k] ~= data[k] then -- 散热风扇附近温度 sensors.set_fan_tmp(data[k], data[k]) end SdbConfig[k] = data[k] or v end configuration.set("SDB", SdbConfig) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function get_config(data) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 for k, v in pairs(SdbConfig) do ack.tags[k] = v end sendAck(data.sn, data.identifier, ack) end local function set_warn_config(data) --log_print.info(cjson.encode(data)) local ChTemperature = cjson.decode(data.ChTemperature) local ChOverVoltage = cjson.decode(data.ChOverVoltage) local ChOverCurrent = cjson.decode(data.ChOverCurrent) local ChResidualCurrent = cjson.decode(data.ChResidualCurrent) local ChOverPower = cjson.decode(data.ChOverPower) for k, v in pairs(data) do if type(v) ~= "string" then WarnConfig[k] = data[k] or v end end WarnConfig.ChTemperature = ChTemperature WarnConfig.ChOverVoltage = ChOverVoltage WarnConfig.ChOverCurrent = ChOverCurrent WarnConfig.ChResidualCurrent = ChResidualCurrent WarnConfig.ChOverPower = ChOverPower isSetWarn = true configuration.set("Warn", WarnConfig) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function get_warn_config(data) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 for k, v in pairs(WarnConfig) do ack.tags[k] = v end sendAck(data.sn, data.identifier, ack) end local function door_unlock(data) sensors.unlock(data.LockNum) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function set_channel(data) sensors.set_chn(data.Config) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function get_warning(data) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = WarnStatus.warnings_all sendAck(data.sn, data.identifier, ack) --WarnStatus.warnings_all = {} end local function control_aws(data) local result = sensors.set_asw_output(data.lt, data.value) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = result and 0 or 1 sendAck(data.sn, data.identifier, ack) end local function set_auto(data) if SdbConfig.Auto ~= data.Auto then SdbConfig.Auto = data.Auto RUN_MODE = SdbConfig.Auto end isAuto = true configuration.set("SDB", SdbConfig) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function cal_sche(data) schedule.cal_sche() local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function set_camera(data) sensors.set_camera(data) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 sendAck(data.sn, data.identifier, ack) end local function get_camera(data) local ack = {} ack.sn = data.sn ack.mi = data.mi ack.time = os.time() ack.identifier = data.identifier ack.tags = {} ack.tags.errorCode = 0 for k, v in pairs(CameraConfig) do ack.tags[k] = v end sendAck(data.sn, data.identifier, ack) end function protocol.isStrategy() return Strategy_chn end function protocol.resetStrategy(ch) Strategy_chn[ch] = false end function protocol.isSetWarn() return isSetWarn end function protocol.resetWarn(value) isSetWarn = value end function protocol.isAuto() return isAuto end function protocol.resetAuto(value) isAuto = value end function protocol.process(topic, payload) local obj = cjson.decode(payload) local service = obj.identifier local services = { SDBGetState = get_state, SDBGetWarning = get_warning, SDBSetSwitchTime = set_schedule, SDBGetSwitchTime = get_schedule, SDBControlSwitch = control_switch, -- 控制开关(远程手动) SDBSetConfig = set_config, SDBGetConfig = get_config, SDBSetWarnConfig = set_warn_config, SDBGetWarnConfig = get_warn_config, SDBUnlock = door_unlock, SDBSetChn = set_channel, -- 设置通道配置参数 SDBControlAWS = control_aws, SDBSetAuto = set_auto, SDBCalSche = cal_sche, SDBSetCamera = set_camera, SDBGetCamera = get_camera } sys.taskInit(function() services[service](obj) end) end function protocol.report(data) local obj = {} obj.mi = os.time() obj.identifier = "SDBReportState" obj.sn = SDB_SN get_state(obj, true, data) -- sensors.get_do_status() -- local sensor_status = sensor_monitor.get_status() -- local ack = {} -- ack.sn = SDB_SN -- ack.mi = 0 -- ack.time = os.time() -- ack.identifier = "SDBReportState" -- --ack.data_type = 1 -- ack.tags = {} -- for k, v in pairs(sensor_status.TempHumi.tags) do -- ack.tags[k] = v -- end -- for k, v in pairs(sensor_status.ADIO.tags) do -- ack.tags.DI = sensor_status.ADIO.tags.DI -- end -- ack.tags.DO = "" -- for i = 1, 8, 1 do -- ack.tags.DO = ack.tags.DO .. (bit.band(sensor_status.ADIO.tags.DO or 0, bit.lshift(1, i - 1)) == 0 and 0 or 1) -- end -- for k, v in pairs(sensor_status.PowerMeter.tags) do -- ack.tags[k] = v -- end -- --sendAck(data.sn, data.identifier, ack) -- mqtt_client.send("ipc/" .. GW_SN .. "/" .. APP_KEY .. "/device/" .. SDB_SN .. "/data_filtered/event/" .. "SDBReportState", cjson.encode(ack)) end function protocol.report_warning(data) for k, v in pairs(data) do warnings[k] = v end local ack = {} ack.sn = SDB_SN ack.mi = os.time() ack.time = os.time() ack.identifier = "SDBReportWarning" ack.tags = data mqtt_client.send("ipc/" .. GW_SN .. "/" .. APP_KEY .. "/device/" .. SDB_SN .. "/data_filtered/event/" .. "SDBReportWarning", cjson.encode(ack)) end function protocol.take_photo(chn) sys.taskInit(function() sys.wait(CameraConfig.time * 1000) for i = 1, CameraConfig.count, 1 do -- 抓拍次数 sensors.get_camera_image(chn) sys.wait(500) end end) end return protocol