# SRP_control **Repository Path**: dai_pei/srp_control ## Basic Information - **Project Name**: SRP_control - **Description**: srp软件组原始中控软件代码 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-10-08 - **Last Updated**: 2022-10-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # rcc ``` PS C:\Users\Kim\Desktop\rcc> node -v v16.14.0 PS C:\Users\Kim\Desktop\rcc> npm -v 8.5.4 PS C:\Users\Kim\Desktop\rcc> vue -V @vue/cli 5.0.1 PS C:\Users\Kim\Desktop\rcc> py -V Python 3.10.4 PS C:\Users\Kim\Desktop\rcc> pip -V pip 22.0.4 from C:\Users\Kim\AppData\Local\Programs\Python\Python310\lib\site-packages\pip (python 3.10) ``` [electron](https://www.electronjs.org/) [vue](https://staging-cn.vuejs.org/guide/quick-start.html) [Vue CLI Plugin Electron Builder](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/) [Node.js](https://nodejs.org/en/docs/) ## Project setup ``` npm install ``` ### Compiles and hot-reloads for development ``` npm run serve ``` ### Compiles and minifies for production ``` npm run build ``` ### Lints and fixes files ``` npm run lint ``` ### Customize configuration See [Configuration Reference](https://cli.vuejs.org/config/). ### Compiles and hot-reloads for development by electron ``` npm run electron:serve ``` ### Compiles and minifies for production by electron ``` npm run electron:build ``` # About ## TODO - [ ] 机器人网络初始化 - [ ] 电脑连接机器人热点 - [ ] 电脑给机器人发送 SSID 和密码(共同网络)❗ - [ ] 电脑接收机器人是否连接成功反馈(选)❗ - [ ] 机器人 MQTT 初始化 - [ ] 电脑连接对应 MQTT 并选择订阅主题 - [ ] 电脑将对应主题发送至对应机器人 - [ ] 电脑接收机器人连接成功反馈 ❗ - [ ] 方式 1:心跳机制(待研究) - [ ] 方式 2:机器人对一个新主题一段时间发布一次心跳消息 ❗ - [ ] 电脑显示连接状态 - [ ] 机器人列表功能 - [ ] 机器人列表的展示 - [ ] 机器人列表的维护 ❗ - [ ] 机器人的删除 - [ ] 音乐的选择处理 - [ ] 用户选择音乐(示例音乐) - [ ] 调用本地音乐解析代码 - [ ] 代码返回音乐解析结果 -❗ - [ ] 用户选择音乐指令执行 - [ ] 用户查看音乐播放状态 - [ ] 暂停音乐指令传输 - [ ] 音乐指令执行 - [ ] 音乐指令发送方式 - [ ] 音乐指令发送 ## 有多少类用户人群呢? 1. 机器人尚未初始化,需要连接热点&发送 SSID,password,ip,topic,heartbeatTopic 1.1 自动连接 1.2 手动连接 2. 机器人已经初始化,但不在列表中,则只需要添加 topic 和 heartbeatTopic 3. 机器人 Mqtt 服务器配置改动后不能用 4. 本地执行 mqtt 服务端,而不使用服务器 ## Warning ### 功能需求 需要连接多个机器人 ## 难点 ### 到底怎么全局维护一个 mqtt client 而不用每次连接? ### 还是说每次都重新连接也没关系?(实际上为了接收机器人的心跳包,所以并不能每次都重新连接)所以必然不能重新连接 ### ## 思路 ### 引入全局状态存储 vuex 或者 pinia 存储 mqtt 客户端以及机器人连接列表 #### 将 mqtt 客户端配置持久化存储 ``` npm i -S pinia npm i -S pinia-plugin-persist ``` #### 加入机器人操作函数 #### 怎么在别处接收 mqtt 客户端接收到的信息? ### 机器人网络初始化 #### 使用 http (axios 跟板子通信) ### 机器人网络连接界面优化 #### 在用户界面显示打开 wifi 按钮及提供 wifi 列表及连接功能 这个 ### 路由子页面 ### 通过 vue 打包的 electron 无法调用 node 的 child_process,可能不得不用 electron 官方的 electron-vue // TODO 在 background.js 加入 node 的执行,另外写一个 js 用 node 执行 https://juejin.cn/post/6844904159821430797 ### 通过 router 跳转的时候会同时出现新旧组件,然后旧组件才消失,影响体验 通过删除 router-view 下的标签即可去除“默认动画” // TODO ### 加入机器人这个操作除了在一开始“同时将 wifi 的 ssid 和 password,需要订阅的主题和心跳主题发送至机器人”这个方法以外,因为存在“用户删除了机器人,但机器人仍保持与 mqtt 服务器连接”的可能,在这种可能的情况下只需要在用户处提供重新连接即可。 // TODO ### 持久化 ->当保存机器人配置的时候将机器人配置持久化 ->当客户端关闭时断开连接 ->当客户端打开客户端时将旧的已经保存的连接重新连接(如果有) ### 机器人列表 el-table 使用 删除机器人按钮 删除机器人确认 机器人名字修改 // TODO 机器人状态展示&实时更新 ### 中期之后的思路 #### 手动连接机器人 1. 机器人代码实现 2. axios 实现连接 3. mqtt 连接断开后怎么重新连接 #### 音乐解析部分 1. 选取文件界面(√) 此处...查阅了很多资料,element-plus 中自带的效果有点难搞,写出自定义的 el-upload 似乎不太简单 先明确我们的需求: ① 只有一个文件能够被选择 ② 用户替换了新的文件的时候旧文件将被替换 ③ 能显示当前所选择文件 ④ 能够获取所选文件的绝对目录 ⑤ 选择后自动解析或者等到决定解析再解析 2. 获取文件路径(√) 使用隐藏 input 来做,并且获取文件路径在 web 中是获取不到的,但目前看来 vue 项目打包成 electron 之后在本地是可以实现的 3. 调用本地 “接口” 并获取返回值(√) [调用命令行程序为 cmd.exe,并运行 cmd 命令](https://juejin.cn/post/6844904159821430797) [Electron 调用命令行(cmd)](http://www.javashuo.com/article/p-sriaagdy-es.html) [Electron-vue 实现后台多进程(一)](https://www.cnblogs.com/webbery/p/12751933.html) 3.1 父子通信(×) [在使用 electron 结合 vue 的时候(并没有用官方的 electron-vue)](https://www.jianshu.com/p/d4d1de286952) [Electron(基于 Vue)中使用 IPC](https://blog.csdn.net/weixin_44171004/article/details/117776842) [Vue CLI Plugin Electron Builder](https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/) 3.2 Node 运行 js 成功(preload.js)(√) Electron 允许您在 Vue 应用程序(共享变量)的上下文中执行带有 Node 集成的 JS 所以思路如下: - 配置 axios 实现对 preload.js 中接口的访问和数据返回 [1](https://blog.csdn.net/xjtarzan/article/details/123682618) - 在 preload.js 中调用 python 脚本并获取返回(是异步的吗?) 3.3 一个使用 express 的例子 4. preload.js nodejs 服务器部分 4.1 接受数据 一个使用 express 的例子 [nodejs 接受前端传来的参数并返回数据](https://www.csdn.net/tags/NtDakgzsMTMzNTEtYmxvZwO0O0OO0O0O.html) 4.2 调用 python 代码 [Nodejs 调用 Python 函数时传递参数](https://blog.51cto.com/u_15127561/4525763) 4.3 返回 json 格式的解析结果 5. 音乐算法 python 部分 5.1 打包 python 文件 打包 python 之后得到一个.bin 文件之后就可以直接运行 [electron python\_在 Electron 应用中运行 python 脚本](https://blog.csdn.net/weixin_33617691/article/details/112027758) [electron-python-example](https://crifan.github.io/desktop_app_framework_electron/website/summary_note/language/python/electron_python_example.html) [electron 打包 php,electron 如何将任意资源打包的方法步骤](https://blog.csdn.net/weixin_35268264/article/details/116531870) [使用 Electron 给 Python 程序加上 GUI](https://zhuanlan.zhihu.com/p/430760821) [Vue 项目中添加一些独立的静态资源(内嵌独立静态页面等)](https://blog.csdn.net/weixin_43680337/article/details/122831857) ``` npm install --save-dev copy-webpack-plugin new CopyPlugin([ { from: 'scripts', to: 'scripts' } ]) ``` errer:unable to locate '/src/scripts' glob ``` 打包时无法通过路径定位到python文件 stderr : C:\Users\Kim\.windows-build-tools\python27\python.exe: can't open file './music.py': [Errno 2] No such file or directory ``` [electron-builder 打包指定资源到安装目录](https://www.jianshu.com/p/9fc6ae1a7317) ``` extraResources: { from: './src/music.py', to: './' } 通过这行代码发现会将py代码打包至C:\Users\Kim\AppData\Local\Programs\rcc\resources 至此,打包成功,在node中获得当前目录再加resource即可 ``` 5.2 python 使用 music21 解析 MIDI 代码 ``` //之所以install不了是因为梯子开着... pip install music21 -i https://mirrors.bfsu.edu.cn/pypi/web/simple/ --trusted-host mirrors.bfsu.edu.cn ``` [python music21 解析 midi 文件为音符](https://blog.51cto.com/u_15177056/5173535) 5.3 是使用 py3 还是 py2.7 呢....解决版本问题...pip ``` Music21 v.4 is the last version that will support Python 2. Please start using Python 3 instead. ``` 5.4 怎么做到本地播放 MIDI 音乐? [vue-aplayer](https://github.com/SevenOutman/vue-aplayer) [ciderapp/Cider](https://github.com/ciderapp/Cider) 5.5 怎么解析 MIDI 音乐? [music21 官方文档](https://web.mit.edu/music21/doc/index.html) [MIDI.js](https://galactic.ink/midi-js/) [npm i midi-player-js](https://www.npmjs.com/package/midi-player-js) [MidiPlayerJS](https://github.com/grimmdude/MidiPlayerJS) ???为什么导入 js 之后在 vue 中找不到相应的内容? [Vue 组件中如何引入外部的 js 文件?](https://juejin.cn/post/6970281486469562375) [浅谈 vue 中 index.html、main.js、App.vue、index.js 之前的关系以及加载过程](https://blog.csdn.net/qq_34182808/article/details/86690193) 5.5.1 MIDI 音乐可以解析为多少种形式? 5.5.2 MIDI 音乐包括什么? + Note:音符 + Chord:和弦 5.5.3 乐理知识补充 ![Image text](https://img-blog.csdnimg.cn/52fbd6315b6645729547306d753774af.png#pic_center) 5.6 怎么做到本地播放音乐跟发送至机器人的指令同步? 5.7 更改了 python 版本之后 npm install 错误 寄 ``` npm install music21j Run "C:\Windows\system32\cmd.exe /d /s /c sh scripts/postinstall.bash" error 错误解决: [找不到 sh](https://blog.csdn.net/zhutubaocsdn/article/details/109229609) 解决方法:修改 git 中的环境变量 ``` 资料记录: 1. [使用 midi.js 写一个可视化钢琴](https://www.ucloud.cn/yun/100672.html) 2. [可视化钢琴](https://qiankun.netlify.app/piano-simulator/#/) 3. [music21 库解析](https://github.com/cuthbertLab/music21j) 4. [自动生成 midi 器](https://vuejsexamples.com/a-tool-for-producing-generative-procedurally-generated-midi-files/) 本来想导入 music21j 进行一些简单运算的,但...music21j 的文档实在不敢恭维。。。(不过现在也获得了 midi 的数据了) #### 设置板块 1. 设置全局的 mqtt 服务器?有用吗 ``` setDir() { const { ipcRenderer } = window.require("electron"); const dir = ipcRenderer.sendSync("dir-select", "x"); console.log("DIR: " + dir); this.c.output_dir = dir.filePaths[0]; }, ``` # 20220422 小记 这几天的思路有点乱, 一来是想要在界面中加入解析 MIDI 的代码然后就能实现像音乐播放器那样的界面,但是尝试引入各种 js 和 npm 下一些包都有实现不了,查了百度谷歌 github 乃至 npm 的包库,emmmmmm.引入 js 之后在 index.js 中引入,但在 vue 中使用不了,到底是哪里没弄对? 二来是 music21-master 里面的解析 MIDI 的代码...照理说应该是可以解析出[时间,乐器的序列],但代码中并没有输出,检查了一番之后打印这个东西在代码中不属于 Note 也不属于 Chord,??? 通过查询 music21 的官方文档和在 python 中查看这个 Measure 看不到到底是个什么东西...可能还可以试试... 三来 ## 先做板子相关的内容吧 [esp8266 写入 micropython 代码](https://blog.csdn.net/yannanxiu/article/details/53966374) [mircopython 固件下载](https://micropython.org/download/esp8266/) [部署固件](http://docs.micropython.org/en/latest/esp8266/tutorial/intro.html#deploying-the-firmware) AP: 32-83-98-B6-00-B3 STA: 30-83-98-B6-00-B3 [upycraft](http://docs.dfrobot.com.cn/upycraft/) ### 安装固件 esptool.py --port COM6 erase_flash esptool.py --port COM6 --baud 9600 write_flash --flash_size=detect 0 esp8266-20220117-v1.18.bin ``` // esptool.py --port COM6 erase_flash esptool.py --port COM6 --baud 9600 write_flash --flash_size=detect 0 esp8266-20220117-v1.18.bin // PS C:\Users\Kim\Desktop> esptool.py --port COM6 --baud 9600 write_flash --flash_size=detect 0 esp8266-20220117-v1.18.bin esptool.py v3.3 Serial port COM6 Connecting.... Detecting chip type... Unsupported detection protocol, switching and trying again... Connecting.... Detecting chip type... ESP8266 Chip is ESP8266EX Features: WiFi Crystal is 26MHz MAC: 30:83:98:b6:00:b3 Uploading stub... Running stub... Stub running... Configuring flash size... Auto-detected Flash size: 4MB Flash will be erased from 0x00000000 to 0x0009bfff... Flash params set to 0x0040 Compressed 635992 bytes to 418427... Wrote 635992 bytes (418427 compressed) at 0x00000000 in 439.6 seconds (effective 11.6 kbit/s)... Hash of data verified. Leaving... Hard resetting via RTS pin... ``` ### 在 uPyCraft 中操作 ``` >>> import os >>> os.listdir() ['analogRead.py', 'blink.py', 'boot.py', 'breatheLight.py', 'digitalRead.py'] >>> import micropython >>> micropython.mem_info() stack: 2096 out of 8192 GC: total: 37952, used: 4336, free: 33616 No. of 1-blocks: 50, 2-blocks: 25, max blk sz: 24, max free sz: 1998 #获得某个类的参数以及函数 >>help(xxx) ``` ### 代码逻辑 1. 启动时,尝试读取设备上保存的 wifi 热点配置文件。如果找不到配置文件,或者连接不上配置文件中的热点,就进入 AP 模式(先不管) 2. 开启 AP 模式,然后等待发送过来的 ssid 和 password,和 mqtt 的参数 3. 然后通过 ssid 和 password 连接 wifi(返回是否连接成功 wifi) 4. 然后通过已经连接好的 wifi 网络环境下去连接 mqtt(返回是否连接成功 mqtt) 5. (话说要不要在连接成功之后关闭 AP 模式?先不管) 参考内容: [micropython(esp8266)adc 采集通过 tcp 发送采集的数据](https://blog.csdn.net/qq_37429313/article/details/117445506) [ESP32 MicroPython 教程:解析 JSON](https://zhuanlan.zhihu.com/p/64300914) ``` import network, socket from machine import ADC, Pin from machine import Pin, PWM import time ip = '192.168.4.1' port = 9999 #端口号 ap = network.WLAN(network.AP_IF) # create access-point interface ap.config(essid='ESP-AP',password='12345678') # set the ESSID of the access point ap.active(True) # activate the interface pwm0 = PWM(Pin(2)) # create PWM object from a pin pwm0.freq(50) # set frequency pwm0.duty(200) # set duty cycle pwm0.duty(int((2.5)/20*1023)) listenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) addr = (ip, port) listenSocket.bind(addr) listenSocket.listen(1) #监听套接字 while True: print("accepting.....") conn, addr = listenSocket.accept() #接收连接请求,返回收发数据的套接字对象和客户端地址 print(addr, "connected") while True: data = conn.recv(1024) #接收数据(1024字节大小) if(len(data) == 0): #判断客户端是否断开连接 print("close socket") conn.close() #关闭套接字 break if(str(data) == "b'1'"): print(data) ret = conn.send(data) #发送数据 pwm0.duty(int((1.3)/20*1023)) time.sleep(5) pwm0.duty(int((2.5)/20*1023)) conn.close() #关闭套接字 break ``` 机器人监听套接字后接收的数据: ``` exec(open('./server.py').read(),globals()) accepting..... ('192.168.4.3', 61640) connected b'GET /?pwd=12345678&mqtthost=1.116.109.176&port=8083&endpoint=%2Fmqtt&name=robot66918&msgtopic=%2FmsgTopic66918&heartbeatTopic=%2FheartbeatTopic66918 HTTP/1.1\r\nHost: 192.168.4.1:9999\r\nConnection: keep-alive\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) rcc/0.1.0 Chrome/91.0.4472.164 Electron/13.6.9 Safari/537.36\r\nReferer: http://localhost:8080/\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN\r\n\r\n' ``` recv()之后怎么拿到 url 呢 看样子并不能通过 API 的方式获得 url,可能通过 decode 之后的字符串类型可以通过 first 去寻找逐个获得参数,但实际上并不好,为了专注在重要的事情上,这一步我选择加入标记分隔符+split 的方式获得。 ``` if(len(data) == 0): #判断客户端是否断开连接 print("close socket") conn.close() #关闭套接字 break if(str(data) == "b'1'"): ret = conn.send(data) #发送数据 time.sleep(4) conn.close() #关闭套接字 break ``` 错误: 1. 处理 OSError: [Errno 9] EBADF 2. net::ERR_INVALID_HTTP_RESPONSE 3. OSError: [Errno 98] EADDRINUSE 这里出现的问题就是什么时候应该关闭连接,弄了好久才改对。这就是网络编程吗。并且这个板子重新加载文件的时候也会因为可能是 fd 文件描述符还是什么的被占用还是什么的报奇奇怪怪的错误,就需要重新启动和连接,然后不停地切换局域网和互联网也是很大的时间开销。 成功返回的代码 ``` import machine from umqtt.simple import MQTTClient pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)] html = """ ESP8266 Pins

ESP8266 Pins

%s
PinValue
""" import socket addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] import network sta_if = network.WLAN(network.STA_IF) sta_if.active(True) sta_if.connect("robot", "12345678") # Connect to an AP print(sta_if.isconnected()) # Check for successful connection ap = network.WLAN(network.AP_IF) # create access-point interface ap.config(essid='ESP-JZ',password='12345678') # set the ESSID of the access point ap.active(True) # activate the interface s = socket.socket() s.bind(addr) s.listen(1) print('listening on', addr) flag = 0 while True: cl, addr = s.accept() print('client connected from', addr) cl_file = cl.makefile('rwb', 0) while True: line = cl_file.readline() #print(line) if(line.decode().startswith("GET /rccrcc")): shuzu = line.decode().split("/rccrcc") ssid = shuzu[1] pwd = shuzu[2] mqtthost = shuzu[3] port = shuzu[4] endpoint = shuzu[5] name = shuzu[6] msgtopic = shuzu[7] heartbeatTopic = shuzu[8] #client = MQTTClient(CLIENT_ID, SERVER) if(line.decode().startswith("GET /test")): print("test") if not line or line == b'\r\n': break #rows = ['%s%d' % (str(p), p.value()) for p in pins] #response = html % '\n'.join(rows) cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') cl.send('{"status":"succuss","info":"communication prepared!"}') #cl.send(response) cl.close() def connectWifi(ssid,pwd): print(ssid,pwd) def mqtt_callback(topic, msg): print('topic: {}'.format(topic)) print('msg: {}'.format(msg)) def connectMQTT(client,callback): print("aaa") ``` 但中间有一段测试也要返回是否可以通信 接下来是在接收到数据之后尝试去连接 wifi 和连接 mqtt 服务器。 search:micropython AP 和 STA 混合模式 search:micropython 连接 mqtt [MicroPython-ESP32 基础教程](http://www.1zlab.com/wiki/micropython-esp32/mqtt/) micropython 如何查看正在运行的 [通俗易懂 一文搞懂 IoT 设备 Wifi 配网 —— ESP32/ESP8266 基于 MicroPython Wifi 配网详解](https://blog.csdn.net/weixin_37272286/article/details/116297086) 开启 AP 模式,监听端口,接收数据,以 STA 模式连接 wifi,并进行 mqtt 连接的 micropython 代码写完放到了./pubilc/robot.main.py 中 开发时所存在的问题: 1. AP 模式开启热点后电脑连接热点但 PING 不通 2. 重启可能会出现 stdio 等错误(占用 fb 或者什么的) 3. AP 模式我明明设置了 wifi 密码但不见了,之前还是好的 4. 带有数据的请求发送至机器人后因为连接 wifi 所需要时间所以返回响应太久所以响应丢失 5. 照理说在网络连接成功之后 AP 模式是会关闭的,但看起来似乎没有被关闭,猜想是可能同时运行着别的与 AP 模式有关的文件。 6. 关闭连接或者短暂断网时应该加载存储的数据,然后进行重新连接 7. 目前是在板子代码中是默认 mqtt 服务器连接不需要用户名和密码的 # 新的需求分析及目标: 1. 正常的音乐解析结果 轨道{ 总长 细分 时间点 } 2. 音乐播放 Soundfont 中的 AudioContext 是需要在 window 下的,所以不能用 node 做 使用 midi-player-js 和 soundfont 进行解析和音乐播放 如果用 node 和 python 解析的话对播放的支持不太好,所以用了这两个库,midi-player-js 对音乐的解析比较简单,感觉分析出来都是单音?不能确定,看不到和弦。并且对于音轨的分析也不够,不能分离出音轨(目前看来),所以对于根据音轨来播放发送音乐的功能似乎.... 3. 轨道绑定机器人 很想得到一个能用的机器人来验证程序的正确与否。->连接部分已经验证过,后续可以直接验证音乐发送部分的正确性。 4. 根据时间发送 时间可以通过 5. wifi 连接提示 this.Player.getTracks()可以获得 midi 的轨道,但会打断当前的播放(?为什么?) 虽然看了源码但是搞不明白,新建了一个 Player 用来分析结果可以解决这个问题。 [MidiPlayerJS 文档](https://grimmdude.com/MidiPlayerJS/docs/player.js.html#line137) 是不是获取某个音轨然后...? [MIDI 音乐下载](https://www.midiclouds.com/) 方案: 设置延迟 设置轨道 音质: ``` { 'Piano': ['1 Acoustic Grand Piano', '2 Bright Acoustic Piano', '3 Electric Grand Piano', '4 Honky-tonk Piano', '5 Electric Piano 1', '6 Electric Piano 2', '7 Harpsichord', '8 Clavinet'], 'Chromatic Percussion': ['9 Celesta', '10 Glockenspiel', '11 Music Box', '12 Vibraphone', '13 Marimba', '14 Xylophone', '15 Tubular Bells', '16 Dulcimer'], 'Organ': ['17 Drawbar Organ', '18 Percussive Organ', '19 Rock Organ', '20 Church Organ', '21 Reed Organ', '22 Accordion', '23 Harmonica', '24 Tango Accordion'], 'Guitar': ['25 Acoustic Guitar (nylon)', '26 Acoustic Guitar (steel)', '27 Electric Guitar (jazz)', '28 Electric Guitar (clean)', '29 Electric Guitar (muted)', '30 Overdriven Guitar', '31 Distortion Guitar', '32 Guitar Harmonics'], 'Bass': ['33 Acoustic Bass', '34 Electric Bass (finger)', '35 Electric Bass (pick)', '36 Fretless Bass', '37 Slap Bass 1', '38 Slap Bass 2', '39 Synth Bass 1', '40 Synth Bass 2'], 'Strings': ['41 Violin', '42 Viola', '43 Cello', '44 Contrabass', '45 Tremolo Strings', '46 Pizzicato Strings', '47 Orchestral Harp', '48 Timpani'], 'Ensemble': ['49 String Ensemble 1', '50 String Ensemble 2', '51 Synth Strings 1', '52 Synth Strings 2', '53 Choir Aahs', '54 Voice Oohs', '55 Synth Choir', '56 Orchestra Hit'], 'Brass': ['57 Trumpet', '58 Trombone', '59 Tuba', '60 Muted Trumpet', '61 French Horn', '62 Brass Section', '63 Synth Brass 1', '64 Synth Brass 2'], 'Reed': ['65 Soprano Sax', '66 Alto Sax', '67 Tenor Sax', '68 Baritone Sax', '69 Oboe', '70 English Horn', '71 Bassoon', '72 Clarinet'], 'Pipe': ['73 Piccolo', '74 Flute', '75 Recorder', '76 Pan Flute', '77 Blown Bottle', '78 Shakuhachi', '79 Whistle', '80 Ocarina'], 'Synth Lead': ['81 Lead 1 (square)', '82 Lead 2 (sawtooth)', '83 Lead 3 (calliope)', '84 Lead 4 (chiff)', '85 Lead 5 (charang)', '86 Lead 6 (voice)', '87 Lead 7 (fifths)', '88 Lead 8 (bass + lead)'], 'Synth Pad': ['89 Pad 1 (new age)', '90 Pad 2 (warm)', '91 Pad 3 (polysynth)', '92 Pad 4 (choir)', '93 Pad 5 (bowed)', '94 Pad 6 (metallic)', '95 Pad 7 (halo)', '96 Pad 8 (sweep)'], 'Synth Effects': ['97 FX 1 (rain)', '98 FX 2 (soundtrack)', '99 FX 3 (crystal)', '100 FX 4 (atmosphere)', '101 FX 5 (brightness)', '102 FX 6 (goblins)', '103 FX 7 (echoes)', '104 FX 8 (sci-fi)'], 'Ethnic': ['105 Sitar', '106 Banjo', '107 Shamisen', '108 Koto', '109 Kalimba', '110 Bagpipe', '111 Fiddle', '112 Shanai'], 'Percussive': ['113 Tinkle Bell', '114 Agogo', '115 Steel Drums', '116 Woodblock', '117 Taiko Drum', '118 Melodic Tom', '119 Synth Drum'], 'Sound effects': ['120 Reverse Cymbal', '121 Guitar Fret Noise', '122 Breath Noise', '123 Seashore', '124 Bird Tweet', '125 Telephone Ring', '126 Helicopter', '127 Applause', '128 Gunshot'] } ``` [【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 )](https://blog.csdn.net/shulianghan/article/details/120873001) 剩余时间有点问题 ->因为其中的 tempo 会改变,而剩余时间是根据 tempo 和其他参数计算出来的,所以剩余时间会改变。 音色目前只能固定一个音色 ->[nameToUrl])(https://github.com/danigb/soundfont-player#nametourlname-soundfont-format--string) ->指定 name 可以使用 name 的合集 json -<但是突然发现 MIDI-player-js 没能解析出音色具体是什么?但 musecoore 可以做到 导入 MIDI.js 之后有点...? -<遇到了错误 Uncaught (in promise) DOMException: The user aborted a request. 获得轨道名的时候乱码... ->尝试使用 py 进行分析 ->py 分析成功 -< node 调用 python 会乱码 ->加入 utf-8 格式的设置代码 ->轨道名显示成功 -<但是通过 music21 显示的轨道和 midi-player-js 显示的轨道不一致,因为 midi-player-js 中会显示一些只显示信息的轨道 -<并且这个标识信息的轨道可能出现在第一段也可能出现在最后一段 ->将数据少于 4 或 10 的轨道省略?发现有 4、5 的都是标识轨道,老师的示例音乐标识轨道在最后,下载的 midi 标识轨道在最前,我制作的没有标识轨道。。 ->可以在分析创建标识轨道的时候判断小于就去掉,然后再分析将轨道名字分配到对应的轨道,因为是按顺序的,希望不会出错 首先排除正在播放的时候用户会删除机器人列表 头疼 选择机器人进行播放的时候 展示的是机器人名字 真实记录的是机器人的 index,然后选取的时候应该也用....? —>思路如下,首先 TrackList 中一定保存的是 robotIndex,因为用 robotIndex 进行对应的发送。 ->el-option 中展示的一定是名字 毕竟没有人看 index -<就是说 ->v-for="(item,index) in pcState"这种方式可以获取 index ->好像解决了 v-for 甚至能通过当前的 v-model 里的值去找 label 的名字 牛逼 待做: 1. MQTT 全局配置(页面,读取...) 2. 机器人状态 3. 如果不想指定机器人?的逻辑 4. 做不了关于动作的绑定,建议后方的机器人在接收动作之后进行分发 5. 用户提示[√] 添加机器人时先检测当前 mqtt 服务器是否正常,正常则跳转至提示 1 页面 如果不正常则提示先配置 MQTT 服务器 6. 单轨发送? 7. 音色调整 8. 有没有一种方法可以等待 MQTT 请求的响应返回? 9. 还有断网的时候的处理[√] 10. 有实时状态呈现[√] 11. 机器端回复 BUG:(有一些无法修复) 1. 音乐的时间在同一个音乐的 tempo 不同的时候会出现计算错误的情况(库自带的 bug) 2. 如果在演奏的过程删除机器人?这种情况概率小,暂且不做处理,属于用户操作出错 3. robotConnectedList 的 Topic 没有检测重复,name 也没有检测重复 4. mqtt 配置页如果填写错误就会有残留的 client 在内存里不断地重连(每次点连接的时候先 end 原来的内容?)(已解决:每次用户点连接的时候 try client.end) 解决问题: 1. 使用全局管理解决调整后 menu 的 active 效果不生效的 bug 2. button 点击后不失焦的 bug 明日计划: 1. 用户指引页面完成 2. 机器人的连接状态更新算法实现 [node.js 调用 ping 命令,并解决乱码问题](https://juejin.cn/post/6844904117060665351) [node.js 怎么调用 ping](https://zhidao.baidu.com/question/395111001141520365.html) [nodejs+express 实现 ping 命令并返回信息](https://blog.csdn.net/qq_34310906/article/details/109582102) [el-table 不随数据改变而改变](https://blog.csdn.net/sven_chen93/article/details/110880675) [esp8266 基于 MicroPython 开启 AP 模式+基于 socket 作为服务端](http://www.gaohaiyan.com/3839.html) - [ ] 本地远程 - [ ] 测试连接 [MQTT 5.0 新特性(四)Clean Start 与 Session Expiry Interval](https://blog.csdn.net/emqx_broker/article/details/100697398) [python 操作 wifi](https://www.cnblogs.com/yhleng/p/9768037.html) 我没找到啊[input 选取文件打开默认路径](https://www.google.com.hk/search?q=input%E9%80%89%E5%8F%96%E6%96%87%E4%BB%B6%E6%89%93%E5%BC%80%E9%BB%98%E8%AE%A4%E8%B7%AF%E5%BE%84%E5%BC%80%E9%BB%98%E8%AE%A4%E8%B7%AF%E5%BE%84) [python 使用 PyGame 播放 Midi 和 Mp3 文件的方法](http://www.zzvips.com/article/75114.html) [pygame.mixer.music--音频](https://www.e-learn.cn/topic/3782877) [物联网工具 Aedes 教程 1:基本介绍(WebSocket)](https://www.v5w.com/iot/500.html) [python 字典顺序不变\_python 字典有顺序吗](https://blog.csdn.net/weixin_39960116/article/details/110536889) 1. 将音轨和音符解析为去重的课选取的列表展现(√) 2. 选取过的不再呈现(x)disable 事件调不了 3. 将选取的列表关系发送至 py 解析得到需要执行的结果 选取关系之后可以知道具体的轨道 index 和音符名,机器人动作 topic, 发送给 py 的逻辑关系结构是: ``` # 绑定发送的数据 { "logic":{ "thicklogic" :[ { "trackIndex":1, "interval":2, "conmandTopic":"/fafag", }, { "trackIndex":1, "interval":2, "conmandTopic":"/fafag2", }, ], "thinlogic":[ { "trackIndex":1, "note":"C5", "actionTopic":"/fafag", "actionIndex":1 }, { "trackIndex":1, "note":"C4", "actionTopic":"/fafag2", "actionIndex":2 }, ] } } ``` 4.最终的结果应该是 【时间,主题,承载】的序列 ``` 接收的发送逻辑关系是 { result:[ { "time":"", "topic":"", "payload":"" }, { "time":"", "topic":"", "payload":"" } ] } ``` [基于 JavaScript 实现 Json 数据根据某个字段进行排序](https://www.jb51.net/article/75325.htm) [Node.js 学习总结-----如何退出用 Node.js 运行的程序](https://segmentfault.com/a/1190000040999915) [Child process 官方文档](https://nodejs.org/api/child_process.html#child_process_child_kill_signal) 在关闭程序的时候同时关闭 python 进程 [python 中对信号的处理详解](https://www.jb51.net/article/216709.htm) 1. SIGINT control+c 2. SIGTERM 终止进程 软件终止信号 3. SIGKILL 终止进程 杀死进程 node 中发送关闭信号至 python 后发现原来进程被删了但是实际上没有被删,反而换了一个进程号在运行(已修复) ``` netstat -aon|findstr "5000" PS C:\Users\Kim\Desktop\rcc> netstat -aon|findstr "5000" TCP 127.0.0.1:5000 0.0.0.0:0 LISTENING 50996 TCP 127.0.0.1:5000 0.0.0.0:0 LISTENING 61000 TCP 127.0.0.1:5000 127.0.0.1:55485 TIME_WAIT 0 TCP 127.0.0.1:5000 127.0.0.1:55486 TIME_WAIT 0 PS C:\Users\Kim\Desktop\rcc> netstat -aon|findstr "5000" TCP 127.0.0.1:5000 0.0.0.0:0 LISTENING 61000 TCP 127.0.0.1:5000 127.0.0.1:55485 TIME_WAIT 0 TCP 127.0.0.1:5000 127.0.0.1:55486 TIME_WAIT 0 TCP 127.0.0.1:5000 127.0.0.1:55509 TIME_WAIT 0 TCP 127.0.0.1:5000 127.0.0.1:55510 TIME_WAIT 0 ``` 如果 interval 是 2,代表如果停止时间大于等于 2s 时,从在此次停止时间前的一次停止发送 STOP,在后续开始时发送 START 如果 interval 是 0 ,代表如果停止时间大于 0 时,从此次停止时间前的一次停止发送 xxx 事实上音符间隔会大于 0, 如果等于 0 的话,相当于每个音符发生的时候就发送 START 结束时发送 STOP? 所以 interval 默认间隔为 2,然后再让用户增加或者减少。 [Python flask 接收 json 数据,requests 发送 post 请求发送 json 数据](https://blog.csdn.net/u012206617/article/details/124272852) [flask 后端接收 POST 数据的三种格式探究](https://blog.csdn.net/w55100/article/details/110943689) [js 用下标获取 map 值\_javascript 怎么获取 map 的值?](https://blog.csdn.net/weixin_35723924/article/details/113391874) [插件 pinia-plugin-persist 可以辅助实现数据持久化功能](https://juejin.cn/post/7057443820115329055) 论文部分: 1. [用例图这样画,3 步让你做需求分析有理有据](https://www.niaogebiji.com/pc/article/detail/?aid=74981) // TODO [√] 将结果定时发布,演奏效果 [] 选择某一项时进行动作 [] 持久化客户端 [] 选中后无法再选 [] 静音播放 [] 如果只有一个音符会出现-2 和-1 同时出现的情况(但我先不管了) [] 断开客户端后重连需要重新订阅 ``` esptool.py --port COM6 flash_id esptool.py --port COM6 erase_flash esptool.py --port COM6 --baud 9600 write_flash --flash_size=detect 0 firmware_esp8266-v1.3.5.bin ``` [Micropython: 解决 Esp8266 没有多线程,使用异步的方式执行多个任务](http://www.wanyor.com/2021/02/24/244.html) [electron 制作上位机软件篇(二)使用 serialport 进行串口通信](http://t.zoukankan.com/flypig666-p-12841340.html) [Electron 使用 serialport 实现串口交互通讯](https://blog.csdn.net/ABC__789/article/details/123664815)