talk.lua 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. -- talk.lua
  2. local talk = {}
  3. dnsproxy = require("dnsproxy")
  4. dhcpsrv = require("dhcpsrv")
  5. httpplus = require("httpplus")
  6. local run_state = false
  7. local input_method = require "InputMethod"
  8. local input_key = false
  9. local g_dev_list = {}
  10. local airaudio = require "airaudio"
  11. extalk = require("extalk")
  12. local local_id
  13. -- 初始化fskv
  14. AIRTALK_TASK_NAME = "airtalk_task"
  15. USER_TASK_NAME = "user"
  16. SUCC = "success"
  17. local speech_topic = nil
  18. local event = ""
  19. local talk_state = ""
  20. -- 新增通讯录相关变量
  21. local address_list_page = 1 -- 通讯录当前页码
  22. local address_list_max_page = 1 -- 通讯录最大页码
  23. local current_page = "main" -- 当前页面状态
  24. local contacts_per_page = 8 -- 每页显示的联系人数量
  25. local function contact_list(dev_list)
  26. g_dev_list = dev_list
  27. for i=1,#dev_list do
  28. log.info("联系人ID:",dev_list[i]["id"],"名称:",dev_list[i]["name"])
  29. end
  30. end
  31. local function state(event_table)
  32. if event_table.state == extalk.START then
  33. log.info("对讲开始,可以说话了")
  34. talk_state = "对讲开始,可以说话了"
  35. elseif event_table.state == extalk.STOP then
  36. log.info("对讲结束")
  37. talk_state = "对讲结束"
  38. elseif event_table.state == extalk.UNRESPONSIVE then
  39. log.info("对端未响应")
  40. talk_state = "对端未响应"
  41. elseif event_table.state == extalk.ONE_ON_ONE then
  42. for i=1,#g_dev_list do
  43. if g_dev_list[i]["id"] == event_table.id then
  44. log.info(g_dev_list[i]["name"],",来电话了")
  45. talk_state = g_dev_list[i]["name"]..",来电话了"
  46. break
  47. end
  48. end
  49. elseif event_table.state == extalk.BROADCAST then
  50. for i=1,#g_dev_list do
  51. if g_dev_list[i]["id"] == event_table.id then
  52. log.info(g_dev_list[i]["name"],"开始广播")
  53. talk_state = g_dev_list[i]["name"].."开始广播"
  54. break
  55. end
  56. end
  57. end
  58. end
  59. local extalk_configs = {
  60. key = PRODUCT_KEY, -- 项目key,一般来说需要和main 的PRODUCT_KEY保持一致
  61. heart_break_time = 120, -- 心跳间隔(单位秒)
  62. contact_list_cbfnc = contact_list, -- 联系人回调函数,回调信息含设备号和昵称
  63. state_cbfnc = state, --状态回调,分为对讲开始,对讲结束,未响应
  64. }
  65. local function init_talk()
  66. log.info("init_call")
  67. airaudio.init() -- 初始化音频
  68. extalk.setup(extalk_configs) -- airtalk 初始化
  69. end
  70. -- 绘制通讯录页面
  71. local function draw_address_list()
  72. lcd.clear(_G.bkcolor)
  73. -- 绘制返回按钮 (左上角)
  74. lcd.showImage(10, 10, "/luadb/back.jpg")
  75. -- 绘制标题 (居中)
  76. lcd.drawStr(120, 30, "通讯录")
  77. -- 计算当前页的联系人起始和结束索引
  78. local start_index = (address_list_page - 1) * contacts_per_page + 1
  79. local end_index = math.min(start_index + contacts_per_page - 1, #g_dev_list)
  80. -- 绘制联系人列表
  81. local y_pos = 78
  82. for i = start_index, end_index do
  83. local contact = g_dev_list[i]
  84. -- 绘制ID
  85. lcd.drawStr(10, y_pos, "ID: " .. (contact["id"] or ""))
  86. -- 绘制名称
  87. lcd.drawStr(10, y_pos + 15, "名称: " .. (contact["name"] or "未知"))
  88. -- 绘制分隔线
  89. lcd.drawLine(5, y_pos + 35-12, 315, y_pos + 35-12)
  90. y_pos = y_pos + 40 -- 每个联系人占40像素高度
  91. end
  92. -- 绘制翻页按钮 (底部居中)
  93. local page_btn_y = 412
  94. if address_list_page > 1 then
  95. lcd.drawStr(50, page_btn_y, "上一页")
  96. end
  97. if address_list_page < address_list_max_page then
  98. lcd.drawStr(220, page_btn_y, "下一页")
  99. end
  100. -- 绘制页码信息 (底部居中)
  101. lcd.drawStr(140, page_btn_y, address_list_page .. "/" .. address_list_max_page)
  102. -- 如果正在通话,绘制停止按钮 (底部居中)
  103. if g_state == SP_T_CONNECTED then
  104. lcd.fill(120, 435, 200, 465,0xF061) -- 绘制停止按钮边框
  105. lcd.drawStr(130, 462, "停止通话")
  106. end
  107. lcd.flush()
  108. end
  109. function talk.run()
  110. log.info("talk.run",airtalk.PROTOCOL_DEMO_MQTT_16K,mobile.imei())
  111. lcd.setFont(lcd.font_opposansm12_chinese)
  112. run_state = true
  113. local_id = mobile.imei()
  114. sys.taskInitEx(init_talk, USER_TASK_NAME)
  115. speech_topic = fskv.get("talk_number")
  116. log.info("get speech_topic",speech_topic)
  117. while run_state do
  118. sys.wait(100)
  119. if input_method.is_active() then
  120. input_method.periodic_refresh()
  121. else
  122. if current_page == "main" then
  123. lcd.clear(_G.bkcolor)
  124. if speech_topic == nil then
  125. lcd.drawStr(0, 80, "所有要对讲的设备,要保持在线")
  126. lcd.drawStr(0, 100, "方案介绍:airtalk.luatos.com")
  127. lcd.drawStr(0, 120, "平台端网址:airtalk.openluat.com/talk/")
  128. lcd.drawStr(0, 140, "本机ID:" .. local_id)
  129. lcd.showImage(32, 250, "/luadb/input_topic.jpg")
  130. lcd.showImage(32, 300, "/luadb/broadcast.jpg")
  131. lcd.showImage(104, 400, "/luadb/stop.jpg")
  132. else
  133. -- lcd.drawStr(0, 80, "对端ID:"..speech_topic )
  134. lcd.drawStr(0, 100, "方案介绍:airtalk.luatos.com")
  135. lcd.drawStr(0, 120, "平台端网址:airtalk.openluat.com/talk/")
  136. lcd.drawStr(0, 140, "所有要对讲的设备,要保持在线")
  137. lcd.drawStr(0, 160, talk_state)
  138. lcd.drawStr(0, 180, "事件:" .. event)
  139. lcd.drawStr(0, 200, "本机ID:" .. local_id)
  140. lcd.drawQrcode(185, 148, "https://airtalk.openluat.com/talk/", 82)
  141. lcd.drawStr(185, 242, "扫码进入网页端",0x0000)
  142. -- 显示输入法入口按钮
  143. lcd.showImage(175, 300, "/luadb/datacall.jpg")
  144. lcd.showImage(32, 300, "/luadb/broadcast.jpg")
  145. lcd.showImage(104, 400, "/luadb/stop.jpg")
  146. lcd.showImage(0, 448, "/luadb/Lbottom.jpg")
  147. end
  148. -- 显示通讯录按钮 (位置x10,y250)
  149. lcd.showImage(175, 250, "/luadb/addresslist.jpg")
  150. lcd.showImage(0,0,"/luadb/back.jpg")
  151. lcd.flush()
  152. elseif current_page == "address_list" then
  153. draw_address_list()
  154. end
  155. end
  156. if not run_state then
  157. return true
  158. end
  159. end
  160. end
  161. local function stop_talk()
  162. talk_state = "停止对讲"
  163. extalk.stop() -- 停止对讲
  164. end
  165. local function start_talk()
  166. if extalk.start(speech_topic) then
  167. talk_state = "发起一对一通话中...."
  168. end
  169. end
  170. local function start_broadcast()
  171. talk_state = "语音采集上传中,正在广播"
  172. extalk.start() -- 开始广播
  173. end
  174. -- 打开通讯录
  175. local function open_address_list()
  176. if g_dev_list == nil or #g_dev_list == 0 then
  177. talk_state = "联系人列表获取失败,检测key和群组是否建立"
  178. log.info("联系人列表获取失败,检测key和群组是否建立")
  179. return false
  180. else
  181. current_page = "address_list"
  182. address_list_page = 1
  183. end
  184. end
  185. -- 返回主页面
  186. local function back_to_main()
  187. current_page = "main"
  188. end
  189. -- 选择联系人
  190. local function select_contact(index)
  191. local contact_index = (address_list_page - 1) * contacts_per_page + index
  192. if contact_index <= #g_dev_list then
  193. local contact = g_dev_list[contact_index]
  194. if contact and contact["id"] then
  195. speech_topic = contact["id"]
  196. fskv.set("talk_number", speech_topic)
  197. start_talk()
  198. -- 对讲开始后返回到主页面
  199. back_to_main()
  200. end
  201. end
  202. end
  203. -- 处理通讯录页面的触摸事件
  204. local function handle_address_list_touch(x, y)
  205. -- 返回按钮区域 (左上角)
  206. if x > 10 and x < 50 and y > 10 and y < 50 then
  207. back_to_main()
  208. return
  209. end
  210. -- 上一页按钮区域 (底部左侧)
  211. if address_list_page > 1 and x > 40 and x < 90 and y > 390 and y < 420 then
  212. address_list_page = address_list_page - 1
  213. return
  214. end
  215. -- 下一页按钮区域 (底部右侧)
  216. if address_list_page < address_list_max_page and x > 210 and x < 260 and y > 390 and y < 420 then
  217. address_list_page = address_list_page + 1
  218. return
  219. end
  220. -- 停止通话按钮区域 (底部居中)
  221. if g_state == SP_T_CONNECTED and x > 120 and x < 200 and y > 435 and y < 465 then
  222. stop_talk()
  223. return
  224. end
  225. -- 联系人选择区域 (60-380像素高度)
  226. if y >= 60 and y <= 380 then
  227. local contact_index = math.floor((y - 60) / 40) + 1
  228. if contact_index >= 1 and contact_index <= contacts_per_page then
  229. select_contact(contact_index)
  230. end
  231. end
  232. end
  233. function talk.tp_handal(x, y, event)
  234. if input_key then
  235. input_method.process_touch(x, y)
  236. else
  237. if current_page == "main" then
  238. if x > 0 and x < 80 and y > 0 and y < 80 then
  239. run_state = false
  240. elseif x > 173 and x < 284 and y > 300 and y < 345 then
  241. sysplus.taskInitEx(start_talk, "start_talk")
  242. elseif x > 32 and x < 133 and y > 300 and y < 345 then
  243. sysplus.taskInitEx(start_broadcast, "start_broadcast")
  244. elseif x > 104 and x < 215 and y > 397 and y < 444 then
  245. sysplus.taskInitEx(stop_talk, "stop_talk")
  246. elseif x > 175 and x < 286 and y > 250 and y < 295 then -- 通讯录按钮
  247. sysplus.taskInitEx(open_address_list, "open_address_list")
  248. end
  249. elseif current_page == "address_list" then
  250. handle_address_list_touch(x, y)
  251. end
  252. end
  253. end
  254. return talk