NeiMengGuServer.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. const os = require("os");
  2. // 获取本机IP地址
  3. function getLocalIP() {
  4. const interfaces = os.networkInterfaces();
  5. for (const iface of Object.values(interfaces)) {
  6. for (const config of iface) {
  7. if (config.family === "IPv4" && !config.internal) {
  8. return config.address;
  9. }
  10. }
  11. }
  12. return "127.0.0.1";
  13. }
  14. //数据格式
  15. let theme = [
  16. { name: "空中成像", val: "历史", switch: "open" },
  17. { name: "文物互动墙", val: "历史", switch: "open" },
  18. { name: "透明展示柜A", val: "历史", switch: "open" },
  19. { name: "透明展示柜B", val: "历史", switch: "open" },
  20. { name: "AI数字人", val: "历史", switch: "open" },
  21. ];
  22. // 通信数据格式
  23. // 1-切换主题
  24. // {type:'cut',data:{ name: "空中成像", val: "红色" }} -----单个切换
  25. // {type:'cut',data:{ name: "all", val: "红色" }} -----全部切换
  26. // 2-开关
  27. // {type:'switch',data:{ name: "空中成像", val: "open"|"close" }'} --单个开关
  28. // {type:'switch',data:{ name: "all", val: "open"|"close" }'} --全部开关
  29. // 3-透明展示柜
  30. let show = [
  31. { name: "A柜左", val: 1 },
  32. { name: "A柜右", val: 2 },
  33. { name: "B柜左", val: 3 },
  34. { name: "B柜右", val: 4 },
  35. ];
  36. // {type:'show',data:{ name: "A柜右", val: 5 }'}
  37. // 4-投屏管理
  38. let screen = [
  39. { name: "户外裸眼3D", val: "close" },
  40. { name: "文物互动墙", val: "close" },
  41. { name: "数字艺术触摸屏", val: "close" },
  42. { name: "AI数字人", val: "close" },
  43. ];
  44. // {type:'screen',data:{ name: "户外裸眼3D", val: "open" }'}
  45. const localIP = getLocalIP();
  46. const port = 8501;
  47. const io = require("socket.io")(port, {
  48. path: "/websocket/",
  49. pingInterval: 30005,
  50. pingTimeout: 5000,
  51. upgradeTimeout: 3000,
  52. allowUpgrades: true,
  53. cookie: false,
  54. serveClient: true,
  55. });
  56. console.log("Socket.IO 服务器已启动!");
  57. console.log("本机访问地址: http://localhost:" + port);
  58. console.log("局域网访问地址: http://" + localIP + ":" + port);
  59. io.on("connection", (socket) => {
  60. console.log("✅ 用户通过 Socket.IO 连接成功:", socket.id);
  61. io.emit("UpdateDeviceInfo", { type: "cut", data: theme });
  62. io.emit("UpdateDeviceInfo", { type: "show", data: show });
  63. io.emit("UpdateDeviceInfo", { type: "screen", data: screen });
  64. socket.on("ChangeDeviceInfo", (info) => {
  65. const { name, val } = info.data;
  66. if (info.type === "cut") {
  67. theme = theme.map((v) => ({
  68. ...v,
  69. val: name === "all" ? val : v.name === name ? val : v.val,
  70. }));
  71. // 然后向前端广播 数据 {type:'cut',data:theme}
  72. io.emit("UpdateDeviceInfo", { type: "cut", data: theme, id: socket.id });
  73. } else if (info.type === "show") {
  74. show = show.map((v) => ({
  75. ...v,
  76. val: v.name === name ? val : v.val,
  77. }));
  78. // 然后向前端广播 数据 {type:'show',data:show}
  79. io.emit("UpdateDeviceInfo", { type: "show", data: show, id: socket.id });
  80. } else if (info.type === "screen") {
  81. screen = screen.map((v) => ({
  82. ...v,
  83. val: v.name === name ? val : v.val,
  84. }));
  85. // 然后向前端广播 数据 {type:'screen',data:screen}
  86. io.emit("UpdateDeviceInfo", {
  87. type: "screen",
  88. data: screen,
  89. id: socket.id,
  90. });
  91. } else if (info.type === "switch") {
  92. theme = theme.map((v) => ({
  93. ...v,
  94. switch: name === "all" ? val : v.name === name ? val : v.switch,
  95. }));
  96. // 然后向前端广播 数据 {type:'cut',data:theme}
  97. io.emit("UpdateDeviceInfo", { type: "cut", data: theme, id: socket.id });
  98. }
  99. });
  100. });
  101. io.on("connection_error", (err) => {
  102. console.log("连接错误:", err.message);
  103. });
  104. io.on("disconnect", (reason) => {
  105. console.log("客户端断开连接:", reason);
  106. });
  107. //tcp协议------------------
  108. const tcpPort = 8052;
  109. const tcpObj = {
  110. // '101' '102'都是字符串
  111. // 空中成像
  112. 101: "空中成像-历史",
  113. 102: "空中成像-红色",
  114. 103: "空中成像-非遗",
  115. // 文物互动墙
  116. 201: "文物互动墙-历史",
  117. 202: "文物互动墙-红色",
  118. 203: "文物互动墙-非遗",
  119. // 透明展示柜A
  120. 301: "透明展示柜A-历史",
  121. 302: "透明展示柜A-红色",
  122. 303: "透明展示柜A-非遗",
  123. // 透明展示柜B
  124. 401: "透明展示柜B-历史",
  125. 402: "透明展示柜B-红色",
  126. 403: "透明展示柜B-非遗",
  127. // AI数字人
  128. 501: "AI数字人-历史",
  129. 502: "AI数字人-红色",
  130. 503: "AI数字人-非遗",
  131. // 切换所有主题
  132. 601: "all-红色",
  133. 602: "all-历史",
  134. 603: "all-非遗",
  135. };
  136. // tcp-server.js
  137. const net = require("net");
  138. const server = net.createServer((socket) => {
  139. console.log("tcp客户端已连接");
  140. socket.on("data", (data) => {
  141. console.log("收到tcp客户端消息:", data.toString());
  142. const valTxt = tcpObj[data.toString()];
  143. if (valTxt) {
  144. const valArr = valTxt.split("-");
  145. const name = valArr[0];
  146. const val = valArr[1];
  147. theme = theme.map((v) => ({
  148. ...v,
  149. val: name === "all" ? val : v.name === name ? val : v.val,
  150. }));
  151. // 然后向前端广播 数据 {type:'cut',data:theme}
  152. io.emit("UpdateDeviceInfo", { type: "cut", data: theme, id: socket.id });
  153. // 回复客户端
  154. socket.write("success");
  155. } else {
  156. console.log(`收到tcp客户端消息:${data.toString()},未找到对应主题`);
  157. socket.write("error: unknown command");
  158. }
  159. });
  160. socket.on("end", () => {
  161. console.log("tcp客户端断开连接");
  162. });
  163. socket.on("error", (err) => {
  164. console.log("tcp客户端连接错误:", err.message);
  165. });
  166. });
  167. server.listen(tcpPort, () => {
  168. console.log("TCP 服务器已启动在 http://" + localIP + ":" + tcpPort);
  169. });