LoRa_Process.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. module(..., package.seeall)
  2. require"radio"
  3. require "sx126x_driver"
  4. -- --------------------- 常量定义 ---------------------
  5. local MASTER_ADDR = 0x00
  6. local MIN_SLAVE_ADDR = 0x01
  7. local MAX_SLAVE_ADDR = 0x05
  8. local QUERY_TIMEOUT_MS = 6
  9. local FRAME_HEADER1 = 0x5A
  10. local FRAME_HEADER2 = 0xA5
  11. local FRAME_TYPE_QUERY = 0x03
  12. local FRAME_TYPE_DATA = 0x02
  13. -- --------------------- 工具函数 ---------------------
  14. -- CRC16 (Modbus)
  15. local function Modbus_CRC16(data, len)
  16. local crc = 0xFFFF
  17. for i = 1, len do
  18. crc = bit.bxor(crc, data[i])
  19. for _ = 1, 8 do
  20. if bit.band(crc, 0x0001) ~= 0 then
  21. crc = bit.rshift(crc,1)
  22. crc = bit.bxor(crc,0xA001)
  23. else
  24. crc = bit.rshift(crc,1)
  25. end
  26. end
  27. end
  28. return bit.rshift(crc,8) + bit.lshift(bit.band(crc,0xFF),8)
  29. end
  30. -- 工具函数:将“十进制字节表”转为“十六进制字符串”(如 {0x5A, 0xA5} → "5AA5")
  31. local function byte_table_to_hex_str(byte_table)
  32. local hex_str = ""
  33. for _, byte_val in ipairs(byte_table) do
  34. -- 确保每个字节转为两位十六进制(不足两位补0,如0x5 → "05")
  35. hex_str = hex_str .. string.format("%02X", byte_val)
  36. end
  37. return hex_str
  38. end
  39. -- 将 {0x5A,0xA5} 转成 "\x5A\xA5" 这种二进制字符串
  40. local function byte_table_to_bin_str(byte_table)
  41. local chars = {}
  42. for i = 1, #byte_table do
  43. chars[i] = string.char(byte_table[i])
  44. end
  45. return table.concat(chars)
  46. end
  47. -- --------------------- 发送查询帧 ---------------------
  48. local function send_query_frame(slave_addr)
  49. log.info("Frame","发送查询帧",slave_addr)
  50. local buf = {
  51. FRAME_HEADER1, FRAME_HEADER2,
  52. MASTER_ADDR, slave_addr,
  53. FRAME_TYPE_QUERY,
  54. 0x00, 0x00 -- reserved
  55. }
  56. local crc = Modbus_CRC16(buf, #buf)
  57. table.insert(buf, bit.band(crc,0xFF)) -- CRC低字节
  58. table.insert(buf, bit.rshift(crc,8)) -- CRC高字节
  59. log.info("查询帧构建完毕,长度="..#buf.."字节")
  60. -- ✅ 转换成二进制字符串
  61. local hex_buf = byte_table_to_hex_str(buf)
  62. local lenHex = string.format("%02X", #buf)
  63. sx126x_driver.RadioSend(hex_buf, lenHex, "00")
  64. -- sys.wait(200)
  65. log.info("查询帧发送完毕,配置的PayloadLength="..#buf)
  66. end
  67. -- -- --------------------- 解析传感器数据 ---------------------
  68. local function bytes_to_float(b1,b2,b3,b4)
  69. local sign = bit.rshift(b4,7)
  70. local expo = bit.band(bit.rshift(b4,0),0x7F) * 2 + bit.rshift(b3,7)
  71. local mant = bit.lshift(bit.band(b3,0x7F),16) + bit.lshift(b2,8) + b1
  72. if expo == 0 then
  73. return 0.0
  74. elseif expo == 255 then
  75. return (mant == 0) and (sign==0 and math.huge or -math.huge) or 0/0
  76. end
  77. return (sign==1 and -1 or 1) * (1 + mant/0x800000) * 2^(expo-127)
  78. end
  79. local function print_sensor(s)
  80. if s.data_type == 0x01 then
  81. local t = bit.lshift(s.data[1],8) + s.data[2]
  82. log.info("Sensor","温度", string.format("%.2f°C", t/100.0))
  83. elseif s.data_type == 0x02 then
  84. local h = bit.lshift(s.data[1],8) + s.data[2]
  85. log.info("Sensor","湿度", string.format("%.2f%%", h/100.0))
  86. elseif s.data_type == 0x03 then
  87. log.info("Sensor","光照强度", s.data[1])
  88. elseif s.data_type == 0x04 then
  89. log.info("Sensor","烟雾浓度", s.data[1])
  90. elseif s.data_type == 0x10 then
  91. if #s.data == 4 then
  92. local val = bytes_to_float(s.data[1],s.data[2],s.data[3],s.data[4])
  93. log.info("Sensor","扩展类型0x10 (float)", string.format("%.4f L", val))
  94. else
  95. log.warn("Sensor","0x10 长度异常", #s.data)
  96. end
  97. else
  98. log.info("Sensor","未知类型", s.data_type, "原始数据", table.concat(s.data,","))
  99. end
  100. end
  101. local function parse_received_frame(hex_str)
  102. log.info("Frame","收到数据", hex_str)
  103. -- 转换 hex_str → buf
  104. local buf = {}
  105. for i = 1, #hex_str, 2 do
  106. local hex_byte = hex_str:sub(i, i+1)
  107. local dec_byte = tonumber(hex_byte, 16)
  108. if not dec_byte then
  109. log.error("Frame","十六进制转换失败", "非法字符:"..hex_byte)
  110. return false
  111. end
  112. table.insert(buf, dec_byte)
  113. end
  114. local buf_len = #buf
  115. if buf_len < 9 then
  116. log.error("Frame","长度不足", buf_len)
  117. return false
  118. end
  119. -- 帧头
  120. if buf[1] ~= FRAME_HEADER1 or buf[2] ~= FRAME_HEADER2 then
  121. log.error("Frame","帧头错误", string.format("实际=0x%02X%02X", buf[1], buf[2]))
  122. return false
  123. end
  124. -- 地址与帧类型
  125. local src_addr = buf[3]
  126. local dst_addr = buf[4]
  127. local frame_type = buf[5]
  128. if dst_addr ~= MASTER_ADDR or frame_type ~= FRAME_TYPE_DATA then
  129. log.error("Frame","地址/类型错误",
  130. string.format("src=0x%02X dst=0x%02X type=0x%02X", src_addr,dst_addr,frame_type))
  131. return false
  132. end
  133. -- 传感器数量+数据总长
  134. local sensor_count = buf[6]
  135. local data_total_len = buf[7]
  136. -- CRC校验
  137. local crc_low, crc_high = buf[buf_len-1], buf[buf_len]
  138. local crc_recv = crc_low + bit.lshift(crc_high,8)
  139. local crc_calc = Modbus_CRC16(buf, buf_len-2)
  140. if crc_recv ~= crc_calc then
  141. log.error("Frame","CRC错误", string.format("recv=0x%04X calc=0x%04X", crc_recv,crc_calc))
  142. return false
  143. end
  144. log.info("Frame","地址=0x"..string.format("%02X",src_addr),
  145. "传感器数="..sensor_count,
  146. "数据长度="..data_total_len.."字节")
  147. -- 逐个解析传感器
  148. local offset = 8
  149. local data_end = 8 + data_total_len - 1
  150. for i = 1, sensor_count do
  151. if offset + 2 > data_end then
  152. log.warn("Frame","传感器头部越界", "offset="..offset)
  153. break
  154. end
  155. local sensor = {
  156. sensor_id = buf[offset],
  157. data_type = buf[offset+1],
  158. data_len = buf[offset+2],
  159. data = {}
  160. }
  161. if offset + 3 + sensor.data_len - 1 > data_end then
  162. log.warn("Frame","传感器数据越界 ID=0x"..string.format("%02X",sensor.sensor_id))
  163. break
  164. end
  165. for j = 1, sensor.data_len do
  166. table.insert(sensor.data, buf[offset+2+j])
  167. end
  168. print_sensor(sensor)
  169. offset = offset + 3 + sensor.data_len
  170. end
  171. return true
  172. end
  173. -- --------------------- 主机轮询 ---------------------
  174. function master_query_loop()
  175. for addr=MIN_SLAVE_ADDR, MAX_SLAVE_ADDR do
  176. sx126x_driver.ReceiveData = ""
  177. log.info("Host","查询从机地址",string.format("0x%02X",addr))
  178. send_query_frame(addr)
  179. local start = os.time()
  180. local response = false
  181. while (os.time()-start) < QUERY_TIMEOUT_MS do
  182. if sx126x_driver.dataReady() then
  183. local rx_buf = sx126x_driver.RadioGetBuffer()
  184. log.info("Host","收到从机数据", "十六进制字符串="..rx_buf)
  185. if rx_buf == "" then
  186. log.info("返回空")
  187. break
  188. end
  189. local slave_addr_hex = string.format("%02X", addr) -- 把当前查询的从机地址转成两位十六进制字符串
  190. log.info("slave_addr_hex",slave_addr_hex)
  191. -- log.info("rx_buf:sub(7,8)",rx_buf:sub(7,8))
  192. -- log.info("rx_buf:sub(5,6)",rx_buf:sub(5,6))
  193. if rx_buf:sub(5,6) ~= slave_addr_hex then
  194. log.info("从机地址不匹配")
  195. break
  196. end
  197. if rx_buf:sub(7,8) ~= "00" then
  198. log.info("主机地址不匹配")
  199. break
  200. end
  201. if parse_received_frame(rx_buf) then
  202. response = true
  203. break
  204. end
  205. end
  206. sys.wait(50)
  207. end
  208. if not response then
  209. log.warn("Host",string.format("从机0x%02X无响应",addr))
  210. end
  211. sys.wait(5000)
  212. end
  213. end
  214. sys.taskInit(function()
  215. sys.wait(5000)
  216. radio.RadioInit()
  217. radio.RadioStandby()
  218. sx126x_driver.RadioSetTxConfig(sx126x_reg.RadioModems_t.MODEM_LORA,"16",0,1,7,"01","0c","00","01","00","00","00",3000)
  219. sx126x_driver.RadioSetChannel(433000000)
  220. sys.wait(2000)
  221. sx126x_driver.RadioRx(0)
  222. local payload = "Hehehe123456"
  223. local num = 1
  224. while true do
  225. master_query_loop()
  226. -- send_query_frame(0x01)
  227. -- RadioStandby()
  228. -- sx126x_driver.sentString("hello,My_name_is_XuXinyi\n")
  229. sys.wait(1500)
  230. log.info("Radio", "测试接收数据中。。。")
  231. -- sx126x_driver.sentString("5AA50005030000093C")
  232. -- sx126x_driver.sentString(payload)
  233. -- sx126x_driver.RadioRx(0)
  234. -- -- -- sx126x_driver.RadioRx(0)
  235. -- sx126x_driver.SX126xWakeup()
  236. -- payload = payload .. num
  237. -- num = num + 1
  238. end
  239. end)