-
holy. freaking. crap. I didn't know there was an argument to the connect callback - the sample code I found didn't have an arg. And yes, putting them inside the callback and using 'socket' made it work. I am now seeing the 0xEF packets being sent. Solved all of the confusion.
As for the UDP code, it does work, but I don't claim to have written it correctly, I'll change it to match the link you provided.
So thanks a million for the corrections!
-
@Robin, I tried your suggestion...seems like a good idea. No difference in results though.
I missed the post about time off, I guess I'll work on other things for a couple weeks, I have plenty of other things to do on this project.
Thanks for your ideas.
-
One more item...the blue LED on the Espruino wifi starts, and continues to, flash/flicker after I get the 'connected' message. So I might actually be getting the 0xEF message, but I'm never getting the tcpClient.on('data', ...) call.
And how do I send a message with tcpClient? tcpClient.write() and tcpClient.send() throw 'undefined' errors.
@Gordon, thoughts?
-
Here is a forum posting from an arduino project that is connecting to a Qu-16 (same series as mine), and I'm doing basically what he's doing: https://forum.arduino.cc/index.php?topic=230326.0
-
Hey, why don't I also include my code?
let udpClient = this.dgram.createSocket('udp4'); udpClient = udpClient.bind(51320, function() { udpClient.on('message', function (msg, info) { console.log(">"+JSON.stringify(msg)); // <- here is where I get 'Qu-SB ...' from the mixer console.log(">"+JSON.stringify(info)); let tcpClient = require('net'); tcpClient.connect({port: 51325, host: "10.1.64.22"}, function() { console.log("connected"); }); tcpClient.on('data', function(chunk) { console.log("tcp data is " + JSON.stringify(chunk)); }); tcpClient.on('end', function() { console.log('client disconnected'); }); }); udpClient.send("QU Find", 0, 7, 51320, "10.1.64.22"); });
10.1.64.22 is the Qu Mixer, which is the Midi device I'm trying to reach.
-
@maze1980 yeah I forgot to add the data, which is super-important, and I've made it a little bit further because I forgot to check wireshark for broadcast packets. So the real A&H driver comms go like this:
Me: UDP 'Qu Find' on 255.255.255.255:51320
MidiDevice: UDP 'Qu-SB' and { address: 10.11.12.13, port: 51320, size: 6 }
Me: TCP connect to 10.11.12.13:51325 // note that 51325 is the TCP port
MidiDevice: TCP 0xEF // <- this is MIDI ActiveSense bit, sent every 300ms forever
Me: TCP ACKSo the data you were asking for is the 0xEF byte, which is what's sent (and ACK'd by 'me') forever. Here's how my Espruino code runs:
Me: UDP 'Qu Find' on 255.255.255.255:52320
(nothing happens, so instead...)
Me: UDP 'Qu Find' on 10.11.12.13:51320 // because I know the IP address already
MidiDevice: UDP 'Qu-SB' and { address: 10.11.12.13, port: 51320, size: 6 }
(cool! so far, so good)
Me: TCP connect to 10.11.12.13:51325
Me: (I get the 'connected' callback, and client.on('data', ...) is never calledSo I'm doing something wrong still, because I don't get the 0xEF message ever.
-
-
@Gordon, to establish and maintain connection to my MIDI device over TCP, I have to send packets with various TCP flags set. In particular, I have to initiate with a SYN, and then respond to future requests with ACK. So it goes like this:
Me: SYN
MIDIDevice: PSH, ACK
Me: ACK
MIDIDevice: PSH,ACK
Me: ACKThat goes on forever. I assume this is just normal keep-alive stuff for TCP connections (I haven't played with TCP at this level for a while).
I got this data by using wireshark and watching how the A&H TCP MIDI driver connected to the mixer. The ACK back-and-forth is what goes on after they connect. When I connect with the Espruino Wifi, it connects and sits there. I assume because I have to send some establishing packet like the A&H driver did (the SYN packet).
Any thoughts on what I'm missing?
-
Thanks, @AkosLukacs, I'm sure there will be some helpful info in there.
-
-
-
@Gordon it looks like the MIDI device (Allen & Heath mixer) communicates using UDP, not TCP. I didn't see a way to specify protocol (TCP, UDP, etc) for the .net library, but I see the choice in NetworkJS. Unless you know something I don't.
-
Yes, MIDI over TCP is just the same MIDI command sequence, only over a TCP connection instead of serial connection. I'm sure there's some kind of "hey this is a MIDI packet" header or something, which I'm still researching, but the MIDI part is typical MIDI.
Thanks for the info, I'll start working on it. And I'd be happy to submit the module to the Espruino project when I'm finished.
-
@Gordon wait, confusion still reigns, my fault not yours. Are you saying that Serial2 is the wifi connection on the Espruino wifi, by default? I don't understand how that would work. I have to send TCP packets over wifi that contains MIDI commands in them, because the target device is listening on TCP for MIDI data. If the target device was a serialport-listening device like normal MIDI, serial port makes sense. Please (try to) clear the fog in my brain. Thanks.
Currently, my plan is to roll my own MIDI implementation using require('Wifi') and require('net'). And by "roll my own" I mean "just enough to get it to work".
-
The target mixer manufacturer (Allen & Heath) published their MIDI spec. It uses NRPN, so minor additional complications, but it's all there.
Re: Wifi server, I don't know yet. Coming from the world of cloud-based software, which is my day job, I think of server as a separate entity with an API and all that. All I need is a listener for MIDI (over TCP) messages from the mixer, and a sender to send the messages. Maybe your definition of server is different from mine. Feel free to expound. I'm checking out the links you provided.
You have a suitcase Rhodes? I'm jealous! Hey you might like my son's music, he's the only kid I know making real music these days - the best of 60's and 70's sound. Check him out: https://open.spotify.com/artist/4ybii90Ofz5HRJyYoTLfiq
-
-
-
Thanks for the suggestion, @allObjects! For some reason, the intermittent load issue has abated, I haven't seen it in the last couple hundred uploads. I haven't shrunken the file size, but I'm also not growing it either.
-
@Gordon I plan to write binary data using the Uint16Array object. The master will send this to one slave, and the slave will respond back with a Uint16Array object. Total bytes in each direction will be < 100 bytes.
Since I want to control the send and receive, I'm thinking of using Serial.write(data), then Serial.read() to receive the response from the slave. But Serial.read() appears to be a blocking call (no callback). So I'm not sure if my idea is the right approach. Thoughts?
-
Thanks, I'll keep everyone updated with my progress, because I'll continue to have questions. I've just started the project a week ago, but am reading/moving the potentiometer, and just ordered a Wifi to start working on comms with the mixer (via WiFi) and the Pico that controls the pot. Those comms are the hard part of this entire project. Not getting them to work, but getting them to work and feel real-timey.
I think I'll also purchase a MDBT42Q and see how it works as a Pico replacement, though I wouldn't use bluetooth. One step at a time.
-
This project will grow obviously, but I think I'm going to use @Gordon's idea of a local webserver to serve them up. Heck, I could just use my bitbucket URLs to the files.
I initially wanted one Wifi to manage the whole thing. Too few pins. So I went with a Pico per channel. I considered a Pico for every 2 channels or 4 channels, which I still might do. It's not like I've sent out for PCBs yet! But I'm starting at 1 each and will go from there.
I haven't checked out the MDBT42Q, I'll do that.
USART for comms, because as I learned from other forums postings of mine, I2C and SPI are master-only. I2C is ideal because it's got built-in multi-device support, but if the Picos can't be I2C slaves, then I'm sunk. Though I found that bridge chip which is cool. But I'm going to first try Gordon's approach using the USART. Because it doesn't require more chips.
-
Well, to be honest, I like the module configuration I have going right now. I'm humming along very nicely in the web IDE environment, and this loading error is a minor issue. I'm doing all my coding in VSCode, which is then loaded using require. Works great. As for the loading issue, I know that it's not a bug in my code, and I'm able to continue just fine because it's intermittent.
I want to reiterate my thanks for all the help you guys have provided on my project, which BTW is an 8-channel MIDI-over-WiFi control surface for the Allen & Heath Qu-SB mixer. One Pico to control each channel, and one Wifi as the Master and communicator with the actual mixer and with the 8 Picos.
-
@Robin, my understanding of the case issues with require is to get the case of the filename right, and my filename is all lowercase. The errors you see are what happens after you get undefined back from require. If the module loads, and it does 90% of the time, I get no errors and my code runs as expected. Note that if this is merely an issue with the chrome extension, and not a "real" issue, I can live with it. Though I wonder what a 300ms wait would do, since I appear to be on the fence.
-
Thanks for the detailed explanation, @Gordon, I understand the sticky wicket you're in. I'll consider a local webserver if things get worse - how long does a static node webserver take to write anyway, like an hour maybe? For the record, I'm on a 2009 Mac Pro (big aluminum tower) with Zeon processors and spinning hard drives. Virus checker? What's that?
Final update on this issue. I have it all working now - I can control my Allen & Heath Qu series mixer via MIDI over TCP using the Espruino Wifi. My high-level understanding was accurate, but you guys helped me figure out how to use the dgram and net libraries properly to make it work. Thanks @Gordon for steering me in the right direction, and @Robin and especially @maze1980 for helping me see the errors in my code. Many thanks.